2008-01-28 21:37:16 +00:00
/* source: socat.c */
2008-02-01 21:26:01 +00:00
/* Copyright Gerhard Rieger 2001-2008 */
2008-01-27 12:00:08 +00:00
/* Published under the GNU General Public License V.2, see file COPYING */
/* this is the main source, including command line option parsing, general
control , and the data shuffler */
# include "config.h"
# include "xioconfig.h" /* what features are enabled */
# include "sysincludes.h"
# include "mytypes.h"
# include "compat.h"
# include "error.h"
# include "sycls.h"
# include "sysutils.h"
# include "dalan.h"
# include "filan.h"
# include "xio.h"
# include "xioopts.h"
2008-02-17 13:59:16 +00:00
# include "xiosigchld.h"
2008-01-27 12:00:08 +00:00
# include "xiolockfile.h"
2008-02-17 13:59:16 +00:00
# include "xioopen.h"
2008-01-27 12:00:08 +00:00
/* command line options */
struct {
bool strictopts ; /* stop on errors in address options */
xiolock_t lock ; /* a lock file */
} socat_opts = {
0 , /* strictopts */
{ NULL , 0 } , /* lock */
} ;
void socat_usage ( FILE * fd ) ;
void socat_version ( FILE * fd ) ;
2008-02-17 13:59:16 +00:00
int socat ( int argc , const char * address1 , const char * address2 ) ;
int _socat ( xiofile_t * xfd1 , xiofile_t * xfd2 ) ;
2008-01-27 12:00:08 +00:00
void socat_signal ( int sig ) ;
void lftocrlf ( char * * in , ssize_t * len , size_t bufsiz ) ;
void crlftolf ( char * * in , ssize_t * len , size_t bufsiz ) ;
static int socat_lock ( void ) ;
static void socat_unlock ( void ) ;
static int socat_newchild ( void ) ;
static const char socatversion [ ] =
# include "./VERSION"
;
static const char timestamp [ ] = __DATE__ " " __TIME__ ;
const char copyright_socat [ ] = " socat by Gerhard Rieger - see www.dest-unreach.org " ;
# if WITH_OPENSSL
const char copyright_openssl [ ] = " This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/) " ;
const char copyright_ssleay [ ] = " This product includes software written by Tim Hudson (tjh@cryptsoft.com) " ;
# endif
bool havelock ;
int main ( int argc , const char * argv [ ] ) {
const char * * arg1 , * a ;
2008-07-24 19:51:38 +00:00
char * mainwaitstring ;
2008-01-27 12:00:08 +00:00
char buff [ 10 ] ;
double rto ;
int i , argc0 , result ;
struct utsname ubuf ;
int lockrc ;
2008-07-24 19:51:38 +00:00
if ( mainwaitstring = getenv ( " SOCAT_MAIN_WAIT " ) ) {
sleep ( atoi ( mainwaitstring ) ) ;
}
2008-01-27 12:00:08 +00:00
diag_set ( ' p ' , strchr ( argv [ 0 ] , ' / ' ) ? strrchr ( argv [ 0 ] , ' / ' ) + 1 : argv [ 0 ] ) ;
/* we must init before applying options because env settings have lower
priority and are to be overridden by options */
2008-02-17 13:59:16 +00:00
if ( xioinitialize ( XIO_MAYALL ) ! = 0 ) {
2008-01-27 12:00:08 +00:00
Exit ( 1 ) ;
}
2008-02-17 13:59:16 +00:00
xiosetopt ( ' p ' , " % " ) ;
2008-01-27 12:00:08 +00:00
xiosetopt ( ' o ' , " : " ) ;
argc0 = argc ; /* save for later use */
arg1 = argv + 1 ; - - argc ;
while ( arg1 [ 0 ] & & ( arg1 [ 0 ] [ 0 ] = = ' - ' ) ) {
switch ( arg1 [ 0 ] [ 1 ] ) {
case ' V ' : socat_version ( stdout ) ; Exit ( 0 ) ;
# if WITH_HELP
case ' ? ' :
case ' h ' :
socat_usage ( stdout ) ;
xioopenhelp ( stdout , ( arg1 [ 0 ] [ 2 ] = = ' ? ' | | arg1 [ 0 ] [ 2 ] = = ' h ' ) ? ( arg1 [ 0 ] [ 3 ] = = ' ? ' | | arg1 [ 0 ] [ 3 ] = = ' h ' ) ? 2 : 1 : 0 ) ;
Exit ( 0 ) ;
# endif /* WITH_HELP */
case ' d ' : diag_set ( ' d ' , NULL ) ; break ;
# if WITH_FILAN
2008-02-17 13:59:16 +00:00
case ' D ' : xioparams - > debug = true ; break ;
2008-01-27 12:00:08 +00:00
# endif
case ' l ' :
switch ( arg1 [ 0 ] [ 2 ] ) {
case ' m ' : /* mixed mode: stderr, then switch to syslog; + facility */
diag_set ( ' s ' , NULL ) ;
xiosetopt ( ' l ' , " m " ) ;
2008-02-17 13:59:16 +00:00
xioparams - > logopt = arg1 [ 0 ] [ 2 ] ;
2008-01-27 12:00:08 +00:00
xiosetopt ( ' y ' , & arg1 [ 0 ] [ 3 ] ) ;
break ;
case ' y ' : /* syslog + facility */
diag_set ( arg1 [ 0 ] [ 2 ] , & arg1 [ 0 ] [ 3 ] ) ;
break ;
case ' f ' : /* to file, +filename */
case ' p ' : /* artificial program name */
if ( arg1 [ 0 ] [ 3 ] ) {
diag_set ( arg1 [ 0 ] [ 2 ] , & arg1 [ 0 ] [ 3 ] ) ;
} else if ( arg1 [ 1 ] ) {
diag_set ( arg1 [ 0 ] [ 2 ] , arg1 [ 1 ] ) ;
+ + arg1 , - - argc ;
} else {
Error1 ( " option -l%c requires an argument; use option \" -h \" for help " , arg1 [ 0 ] [ 2 ] ) ;
}
break ;
case ' s ' : /* stderr */
diag_set ( arg1 [ 0 ] [ 2 ] , NULL ) ;
break ;
case ' u ' :
diag_set ( ' u ' , NULL ) ;
break ;
case ' h ' :
diag_set_int ( ' h ' , true ) ;
break ;
default :
Error1 ( " unknown log option \" %s \" ; use option \" -h \" for help " , arg1 [ 0 ] ) ;
break ;
}
break ;
2008-02-17 13:59:16 +00:00
case ' v ' : xioparams - > verbose = true ; break ;
case ' x ' : xioparams - > verbhex = true ; break ;
2008-01-27 12:00:08 +00:00
case ' b ' : if ( arg1 [ 0 ] [ 2 ] ) {
a = * arg1 + 2 ;
} else {
+ + arg1 , - - argc ;
if ( ( a = * arg1 ) = = NULL ) {
Error ( " option -b requires an argument; use option \" -h \" for help " ) ;
Exit ( 1 ) ;
}
}
2008-02-17 13:59:16 +00:00
xioparams - > bufsiz = strtoul ( a , ( char * * ) & a , 0 ) ;
2008-01-27 12:00:08 +00:00
break ;
case ' s ' :
diag_set_int ( ' e ' , E_FATAL ) ; break ;
case ' t ' : if ( arg1 [ 0 ] [ 2 ] ) {
a = * arg1 + 2 ;
} else {
+ + arg1 , - - argc ;
if ( ( a = * arg1 ) = = NULL ) {
Error ( " option -t requires an argument; use option \" -h \" for help " ) ;
Exit ( 1 ) ;
}
}
rto = strtod ( a , ( char * * ) & a ) ;
2008-02-17 13:59:16 +00:00
xioparams - > closwait . tv_sec = rto ;
xioparams - > closwait . tv_usec =
( rto - xioparams - > closwait . tv_sec ) * 1000000 ;
2008-01-27 12:00:08 +00:00
break ;
case ' T ' : if ( arg1 [ 0 ] [ 2 ] ) {
a = * arg1 + 2 ;
} else {
+ + arg1 , - - argc ;
if ( ( a = * arg1 ) = = NULL ) {
Error ( " option -T requires an argument; use option \" -h \" for help " ) ;
Exit ( 1 ) ;
}
}
rto = strtod ( a , ( char * * ) & a ) ;
2008-02-17 13:59:16 +00:00
xioparams - > total_timeout . tv_sec = rto ;
xioparams - > total_timeout . tv_usec =
( rto - xioparams - > total_timeout . tv_sec ) * 1000000 ;
2008-01-27 12:00:08 +00:00
break ;
2008-02-17 13:59:16 +00:00
case ' u ' : xioparams - > lefttoright = true ; break ;
case ' U ' : xioparams - > righttoleft = true ; break ;
2008-01-27 12:00:08 +00:00
case ' g ' : xioopts_ignoregroups = true ; break ;
case ' L ' : if ( socat_opts . lock . lockfile )
Error ( " only one -L and -W option allowed " ) ;
if ( arg1 [ 0 ] [ 2 ] ) {
socat_opts . lock . lockfile = * arg1 + 2 ;
} else {
+ + arg1 , - - argc ;
if ( ( socat_opts . lock . lockfile = * arg1 ) = = NULL ) {
Error ( " option -L requires an argument; use option \" -h \" for help " ) ;
Exit ( 1 ) ;
}
}
break ;
case ' W ' : if ( socat_opts . lock . lockfile )
Error ( " only one -L and -W option allowed " ) ;
if ( arg1 [ 0 ] [ 2 ] ) {
socat_opts . lock . lockfile = * arg1 + 2 ;
} else {
+ + arg1 , - - argc ;
if ( ( socat_opts . lock . lockfile = * arg1 ) = = NULL ) {
Error ( " option -W requires an argument; use option \" -h \" for help " ) ;
Exit ( 1 ) ;
}
}
socat_opts . lock . waitlock = true ;
socat_opts . lock . intervall . tv_sec = 1 ;
socat_opts . lock . intervall . tv_nsec = 0 ;
break ;
# if WITH_IP4 || WITH_IP6
# if WITH_IP4
case ' 4 ' :
# endif
# if WITH_IP6
case ' 6 ' :
# endif
xioopts . default_ip = arg1 [ 0 ] [ 1 ] ;
xioopts . preferred_ip = arg1 [ 0 ] [ 1 ] ;
break ;
# endif /* WITH_IP4 || WITH_IP6 */
case ' \0 ' :
2008-02-17 13:59:16 +00:00
case ' - ' : /*! this is hardcoded "--" */
2008-01-27 12:00:08 +00:00
case ' , ' :
2008-02-17 13:59:16 +00:00
case ' : ' : break ; /* this "-" is a variation of STDIO or -- */
2008-01-27 12:00:08 +00:00
default :
xioinqopt ( ' p ' , buff , sizeof ( buff ) ) ;
if ( arg1 [ 0 ] [ 1 ] = = buff [ 0 ] ) {
break ;
}
Error1 ( " unknown option \" %s \" ; use option \" -h \" for help " , arg1 [ 0 ] ) ;
Exit ( 1 ) ;
}
/* the leading "-" might be a form of the first address */
xioinqopt ( ' p ' , buff , sizeof ( buff ) ) ;
if ( arg1 [ 0 ] [ 0 ] = = ' - ' & &
( arg1 [ 0 ] [ 1 ] = = ' \0 ' | | arg1 [ 0 ] [ 1 ] = = ' : ' | |
2008-02-17 13:59:16 +00:00
arg1 [ 0 ] [ 1 ] = = ' , ' | | arg1 [ 0 ] [ 1 ] = = ' - ' /*!*/ | |
arg1 [ 0 ] [ 1 ] = = buff [ 0 ] ) )
2008-01-27 12:00:08 +00:00
break ;
+ + arg1 ; - - argc ;
}
2008-02-17 13:59:16 +00:00
#if 0
Info1 ( " %d address arguments " , argc ) ;
# else
2008-01-27 12:00:08 +00:00
if ( argc ! = 2 ) {
Error1 ( " exactly 2 addresses required (there are %d); use option \" -h \" for help " , argc ) ;
Exit ( 1 ) ;
}
2008-02-17 13:59:16 +00:00
# endif
if ( xioparams - > lefttoright & & xioparams - > righttoleft ) {
2008-01-27 12:00:08 +00:00
Error ( " -U and -u must not be combined " ) ;
}
2008-09-22 20:17:55 +00:00
xioinitialize2 ( ) ;
2008-01-27 12:00:08 +00:00
Info ( copyright_socat ) ;
# if WITH_OPENSSL
Info ( copyright_openssl ) ;
Info ( copyright_ssleay ) ;
# endif
Debug2 ( " socat version %s on %s " , socatversion , timestamp ) ;
2008-09-22 20:17:55 +00:00
xiosetenv ( " VERSION " , socatversion , 1 ) ; /* SOCAT_VERSION */
2008-01-27 12:00:08 +00:00
uname ( & ubuf ) ; /* ! here we circumvent internal tracing (Uname) */
Debug4 ( " running on %s version %s, release %s, machine %s \n " ,
ubuf . sysname , ubuf . version , ubuf . release , ubuf . machine ) ;
# if WITH_MSGLEVEL <= E_DEBUG
for ( i = 0 ; i < argc0 ; + + i ) {
Debug2 ( " argv[%d]: \" %s \" " , i , argv [ i ] ) ;
}
# endif /* WITH_MSGLEVEL <= E_DEBUG */
/* not sure what signal should print a message */
Signal ( SIGHUP , socat_signal ) ;
Signal ( SIGINT , socat_signal ) ;
Signal ( SIGQUIT , socat_signal ) ;
Signal ( SIGILL , socat_signal ) ;
/* SIGABRT for assert; catching caused endless recursion on assert in libc
( tzfile . c : 498 : __tzfile_compute : Assertion ' num_types = = 1 ' failed . ) */
/*Signal(SIGABRT, socat_signal);*/
Signal ( SIGBUS , socat_signal ) ;
Signal ( SIGFPE , socat_signal ) ;
Signal ( SIGSEGV , socat_signal ) ;
Signal ( SIGTERM , socat_signal ) ;
2008-02-17 13:59:16 +00:00
# if HAVE_SIGACTION
{
struct sigaction act ;
memset ( & act , 0 , sizeof ( struct sigaction ) ) ;
act . sa_flags = SA_NOCLDSTOP | SA_RESTART | SA_SIGINFO
# ifdef SA_NOMASK
| SA_NOMASK
# endif
;
act . sa_sigaction = xiosigaction_subaddr_ok ;
if ( Sigaction ( SIGUSR1 , & act , NULL ) < 0 ) {
/*! Linux man does not explicitely say that errno is defined */
Warn1 ( " sigaction(SIGUSR1, {&xiosigaction_subaddr_ok}, NULL): %s " , strerror ( errno ) ) ;
}
}
# else /* !HAVE_SIGACTION */
if ( Signal ( SIGUSR1 , xiosigaction_subaddr_ok ) = = SIG_ERR ) {
Warn1 ( " signal(SIGCHLD, xiosigaction_subaddr_ok): %s " , strerror ( errno ) ) ;
}
# endif /* !HAVE_SIGACTION */
2008-01-27 12:00:08 +00:00
/* set xio hooks */
xiohook_newchild = & socat_newchild ;
if ( lockrc = socat_lock ( ) ) {
/* =0: goon; >0: locked; <0: error, printed in sub */
if ( lockrc > 0 )
Error1 ( " could not obtain lock \" %s \" " , socat_opts . lock . lockfile ) ;
Exit ( 1 ) ;
}
Atexit ( socat_unlock ) ;
2008-02-17 13:59:16 +00:00
result = socat ( argc , arg1 [ 0 ] , arg1 [ 1 ] ) ;
2008-01-27 12:00:08 +00:00
Notice1 ( " exiting with status %d " , result ) ;
Exit ( result ) ;
return 0 ; /* not reached, just for gcc -Wall */
}
void socat_usage ( FILE * fd ) {
fputs ( copyright_socat , fd ) ; fputc ( ' \n ' , fd ) ;
fputs ( " Usage: \n " , fd ) ;
fputs ( " socat [options] <bi-address> <bi-address> \n " , fd ) ;
fputs ( " options: \n " , fd ) ;
fputs ( " -V print version and feature information to stdout, and exit \n " , fd ) ;
# if WITH_HELP
fputs ( " -h|-? print a help text describing command line options and addresses \n " , fd ) ;
fputs ( " -hh like -h, plus a list of all common address option names \n " , fd ) ;
fputs ( " -hhh like -hh, plus a list of all available address option names \n " , fd ) ;
# endif /* WITH_HELP */
fputs ( " -d increase verbosity (use up to 4 times; 2 are recommended) \n " , fd ) ;
# if WITH_FILAN
fputs ( " -D analyze file descriptors before loop \n " , fd ) ;
# endif
fputs ( " -ly[facility] log to syslog, using facility (default is daemon) \n " , fd ) ;
fputs ( " -lf<logfile> log to file \n " , fd ) ;
fputs ( " -ls log to stderr (default if no other log) \n " , fd ) ;
fputs ( " -lm[facility] mixed log mode (stderr during initialization, then syslog) \n " , fd ) ;
fputs ( " -lp<progname> set the program name used for logging \n " , fd ) ;
fputs ( " -lu use microseconds for logging timestamps \n " , fd ) ;
fputs ( " -lh add hostname to log messages \n " , fd ) ;
fputs ( " -v verbose data traffic, text \n " , fd ) ;
fputs ( " -x verbose data traffic, hexadecimal \n " , fd ) ;
fputs ( " -b<size_t> set data buffer size (8192) \n " , fd ) ;
fputs ( " -s sloppy (continue on error) \n " , fd ) ;
fputs ( " -t<timeout> wait seconds before closing second channel \n " , fd ) ;
fputs ( " -T<timeout> total inactivity timeout in seconds \n " , fd ) ;
fputs ( " -u unidirectional mode (left to right) \n " , fd ) ;
fputs ( " -U unidirectional mode (right to left) \n " , fd ) ;
fputs ( " -g do not check option groups \n " , fd ) ;
fputs ( " -L <lockfile> try to obtain lock, or fail \n " , fd ) ;
fputs ( " -W <lockfile> try to obtain lock, or wait \n " , fd ) ;
# if WITH_IP4
fputs ( " -4 prefer IPv4 if version is not explicitly specified \n " , fd ) ;
# endif
# if WITH_IP6
fputs ( " -6 prefer IPv6 if version is not explicitly specified \n " , fd ) ;
# endif
}
void socat_version ( FILE * fd ) {
struct utsname ubuf ;
fputs ( copyright_socat , fd ) ; fputc ( ' \n ' , fd ) ;
fprintf ( fd , " socat version %s on %s \n " , socatversion , timestamp ) ;
Uname ( & ubuf ) ;
fprintf ( fd , " running on %s version %s, release %s, machine %s \n " ,
ubuf . sysname , ubuf . version , ubuf . release , ubuf . machine ) ;
fputs ( " features: \n " , fd ) ;
# ifdef WITH_STDIO
fprintf ( fd , " #define WITH_STDIO %d \n " , WITH_STDIO ) ;
# else
fputs ( " #undef WITH_STDIO \n " , fd ) ;
# endif
# ifdef WITH_FDNUM
fprintf ( fd , " #define WITH_FDNUM %d \n " , WITH_FDNUM ) ;
# else
fputs ( " #undef WITH_FDNUM \n " , fd ) ;
# endif
# ifdef WITH_FILE
fprintf ( fd , " #define WITH_FILE %d \n " , WITH_FILE ) ;
# else
fputs ( " #undef WITH_FILE \n " , fd ) ;
# endif
# ifdef WITH_CREAT
fprintf ( fd , " #define WITH_CREAT %d \n " , WITH_CREAT ) ;
# else
fputs ( " #undef WITH_CREAT \n " , fd ) ;
# endif
# ifdef WITH_GOPEN
fprintf ( fd , " #define WITH_GOPEN %d \n " , WITH_GOPEN ) ;
# else
fputs ( " #undef WITH_GOPEN \n " , fd ) ;
# endif
# ifdef WITH_TERMIOS
fprintf ( fd , " #define WITH_TERMIOS %d \n " , WITH_TERMIOS ) ;
# else
fputs ( " #undef WITH_TERMIOS \n " , fd ) ;
# endif
# ifdef WITH_PIPE
fprintf ( fd , " #define WITH_PIPE %d \n " , WITH_PIPE ) ;
# else
fputs ( " #undef WITH_PIPE \n " , fd ) ;
# endif
# ifdef WITH_UNIX
fprintf ( fd , " #define WITH_UNIX %d \n " , WITH_UNIX ) ;
# else
fputs ( " #undef WITH_UNIX \n " , fd ) ;
# endif /* WITH_UNIX */
# ifdef WITH_ABSTRACT_UNIXSOCKET
fprintf ( fd , " #define WITH_ABSTRACT_UNIXSOCKET %d \n " , WITH_ABSTRACT_UNIXSOCKET ) ;
# else
fputs ( " #undef WITH_ABSTRACT_UNIXSOCKET \n " , fd ) ;
# endif /* WITH_ABSTRACT_UNIXSOCKET */
# ifdef WITH_IP4
fprintf ( fd , " #define WITH_IP4 %d \n " , WITH_IP4 ) ;
# else
fputs ( " #undef WITH_IP4 \n " , fd ) ;
# endif
# ifdef WITH_IP6
fprintf ( fd , " #define WITH_IP6 %d \n " , WITH_IP6 ) ;
# else
fputs ( " #undef WITH_IP6 \n " , fd ) ;
# endif
# ifdef WITH_RAWIP
fprintf ( fd , " #define WITH_RAWIP %d \n " , WITH_RAWIP ) ;
# else
fputs ( " #undef WITH_RAWIP \n " , fd ) ;
# endif
2008-09-24 14:15:11 +00:00
# ifdef WITH_GENERICSOCKET
fprintf ( fd , " #define WITH_GENERICSOCKET %d \n " , WITH_GENERICSOCKET ) ;
# else
fputs ( " #undef WITH_GENERICSOCKET \n " , fd ) ;
# endif
2008-09-20 21:37:56 +00:00
# ifdef WITH_INTERFACE
fprintf ( fd , " #define WITH_INTERFACE %d \n " , WITH_INTERFACE ) ;
# else
fputs ( " #undef WITH_INTERFACE \n " , fd ) ;
# endif
2008-01-27 12:00:08 +00:00
# ifdef WITH_TCP
fprintf ( fd , " #define WITH_TCP %d \n " , WITH_TCP ) ;
# else
fputs ( " #undef WITH_TCP \n " , fd ) ;
# endif
# ifdef WITH_UDP
fprintf ( fd , " #define WITH_UDP %d \n " , WITH_UDP ) ;
# else
fputs ( " #undef WITH_UDP \n " , fd ) ;
# endif
2008-09-22 21:21:26 +00:00
# ifdef WITH_SCTP
fprintf ( fd , " #define WITH_SCTP %d \n " , WITH_SCTP ) ;
# else
fputs ( " #undef WITH_SCTP \n " , fd ) ;
# endif
2008-01-27 12:00:08 +00:00
# ifdef WITH_LISTEN
fprintf ( fd , " #define WITH_LISTEN %d \n " , WITH_LISTEN ) ;
# else
fputs ( " #undef WITH_LISTEN \n " , fd ) ;
# endif
# ifdef WITH_SOCKS4
fprintf ( fd , " #define WITH_SOCKS4 %d \n " , WITH_SOCKS4 ) ;
# else
fputs ( " #undef WITH_SOCKS4 \n " , fd ) ;
# endif
# ifdef WITH_SOCKS4A
fprintf ( fd , " #define WITH_SOCKS4A %d \n " , WITH_SOCKS4A ) ;
# else
fputs ( " #undef WITH_SOCKS4A \n " , fd ) ;
# endif
# ifdef WITH_PROXY
fprintf ( fd , " #define WITH_PROXY %d \n " , WITH_PROXY ) ;
# else
fputs ( " #undef WITH_PROXY \n " , fd ) ;
# endif
# ifdef WITH_SYSTEM
fprintf ( fd , " #define WITH_SYSTEM %d \n " , WITH_SYSTEM ) ;
# else
fputs ( " #undef WITH_SYSTEM \n " , fd ) ;
# endif
# ifdef WITH_EXEC
fprintf ( fd , " #define WITH_EXEC %d \n " , WITH_EXEC ) ;
# else
fputs ( " #undef WITH_EXEC \n " , fd ) ;
# endif
# ifdef WITH_READLINE
fprintf ( fd , " #define WITH_READLINE %d \n " , WITH_READLINE ) ;
# else
fputs ( " #undef WITH_READLINE \n " , fd ) ;
# endif
# ifdef WITH_TUN
fprintf ( fd , " #define WITH_TUN %d \n " , WITH_TUN ) ;
# else
fputs ( " #undef WITH_TUN \n " , fd ) ;
# endif
# ifdef WITH_PTY
fprintf ( fd , " #define WITH_PTY %d \n " , WITH_PTY ) ;
# else
fputs ( " #undef WITH_PTY \n " , fd ) ;
# endif
# ifdef WITH_OPENSSL
fprintf ( fd , " #define WITH_OPENSSL %d \n " , WITH_OPENSSL ) ;
# else
fputs ( " #undef WITH_OPENSSL \n " , fd ) ;
# endif
# ifdef WITH_FIPS
fprintf ( fd , " #define WITH_FIPS %d \n " , WITH_FIPS ) ;
# else
fputs ( " #undef WITH_FIPS \n " , fd ) ;
# endif
# ifdef WITH_LIBWRAP
fprintf ( fd , " #define WITH_LIBWRAP %d \n " , WITH_LIBWRAP ) ;
# else
fputs ( " #undef WITH_LIBWRAP \n " , fd ) ;
# endif
# ifdef WITH_SYCLS
fprintf ( fd , " #define WITH_SYCLS %d \n " , WITH_SYCLS ) ;
# else
fputs ( " #undef WITH_SYCLS \n " , fd ) ;
# endif
# ifdef WITH_FILAN
fprintf ( fd , " #define WITH_FILAN %d \n " , WITH_FILAN ) ;
# else
fputs ( " #undef WITH_FILAN \n " , fd ) ;
# endif
# ifdef WITH_RETRY
fprintf ( fd , " #define WITH_RETRY %d \n " , WITH_RETRY ) ;
# else
fputs ( " #undef WITH_RETRY \n " , fd ) ;
# endif
# ifdef WITH_MSGLEVEL
fprintf ( fd , " #define WITH_MSGLEVEL %d /*%s*/ \n " , WITH_MSGLEVEL ,
& " debug \0 \0 \0 info \0 \0 \0 \0 notice \0 \0 warn \0 \0 \0 \0 error \0 \0 \0 fatal \0 \0 \0 " [ WITH_MSGLEVEL < < 3 ] ) ;
# else
fputs ( " #undef WITH_MSGLEVEL \n " , fd ) ;
# endif
}
/* call this function when the common command line options are parsed, and the
addresses are extracted ( but not resolved ) . */
2008-02-17 13:59:16 +00:00
int socat ( int argc , const char * address1 , const char * address2 ) {
xiofile_t * xfd1 , * xfd2 ;
2008-01-27 12:00:08 +00:00
2008-02-17 13:59:16 +00:00
xioinitialize ( XIO_MAYALL ) ;
2008-01-27 12:00:08 +00:00
# if 1
if ( Signal ( SIGPIPE , SIG_IGN ) = = SIG_ERR ) {
Warn1 ( " signal(SIGPIPE, SIG_IGN): %s " , strerror ( errno ) ) ;
}
# endif
2008-02-17 13:59:16 +00:00
/* open the first (left most) address */
if ( xioparams - > lefttoright ) {
if ( ( xfd1 = socat_open ( address1 , XIO_RDONLY , XIO_MAYFORK | XIO_MAYCHILD | XIO_MAYCONVERT ) ) = = NULL ) {
2008-01-27 12:00:08 +00:00
return - 1 ;
}
2008-02-17 13:59:16 +00:00
} else if ( xioparams - > righttoleft ) {
if ( ( xfd1 = socat_open ( address1 , XIO_WRONLY , XIO_MAYFORK | XIO_MAYCHILD | XIO_MAYCONVERT ) ) = = NULL ) {
2008-01-27 12:00:08 +00:00
return - 1 ;
}
} else {
2008-02-17 13:59:16 +00:00
if ( ( xfd1 = socat_open ( address1 , XIO_RDWR , XIO_MAYFORK | XIO_MAYCHILD | XIO_MAYCONVERT ) ) = = NULL ) {
2008-01-27 12:00:08 +00:00
return - 1 ;
}
}
2008-02-17 13:59:16 +00:00
xiosetsigchild ( xfd1 , socat_sigchild ) ;
2008-01-27 12:00:08 +00:00
# if 1 /*! */
2008-02-17 13:59:16 +00:00
if ( XIO_RDSTREAM ( xfd1 ) - > subaddrstat < 0 ) {
Info1 ( " child " F_pid " has already died " ,
XIO_RDSTREAM ( xfd1 ) - > child . pid ) ;
XIO_RDSTREAM ( xfd1 ) - > child . pid = 0 ;
/* return STAT_RETRYLATER; */
2008-01-27 12:00:08 +00:00
}
# endif
2008-02-17 13:59:16 +00:00
/* second (right) addresses chain */
if ( XIO_WRITABLE ( xfd1 ) ) {
if ( XIO_READABLE ( xfd1 ) ) {
if ( ( xfd2 = socat_open ( address2 , XIO_RDWR , XIO_MAYFORK | XIO_MAYCHILD | XIO_MAYEXEC | XIO_MAYCONVERT ) ) = = NULL ) {
2008-01-27 12:00:08 +00:00
return - 1 ;
}
} else {
2008-02-17 13:59:16 +00:00
if ( ( xfd2 = socat_open ( address2 , XIO_RDONLY , XIO_MAYFORK | XIO_MAYCHILD | XIO_MAYEXEC | XIO_MAYCONVERT ) ) = = NULL ) {
2008-01-27 12:00:08 +00:00
return - 1 ;
}
}
} else { /* assuming sock1 is readable */
2008-02-17 13:59:16 +00:00
if ( ( xfd2 = socat_open ( address2 , XIO_WRONLY , XIO_MAYFORK | XIO_MAYCHILD | XIO_MAYEXEC | XIO_MAYCONVERT ) ) = = NULL ) {
2008-01-27 12:00:08 +00:00
return - 1 ;
}
}
2008-02-17 13:59:16 +00:00
xiosetsigchild ( xfd2 , socat_sigchild ) ;
2008-01-27 12:00:08 +00:00
# if 1 /*! */
2008-02-17 13:59:16 +00:00
if ( XIO_RDSTREAM ( xfd2 ) - > subaddrstat < 0 ) {
Info1 ( " child " F_pid " has already died " ,
XIO_RDSTREAM ( xfd2 ) - > child . pid ) ;
XIO_RDSTREAM ( xfd2 ) - > child . pid = 0 ;
/* return STAT_RETRYLATER; */
2008-01-27 12:00:08 +00:00
}
# endif
Info ( " resolved and opened all sock addresses " ) ;
return
2008-02-17 13:59:16 +00:00
_socat ( xfd1 , xfd2 ) ;
2008-01-27 12:00:08 +00:00
}
2008-02-17 13:59:16 +00:00
2008-10-22 00:33:23 +00:00
/* childleftdata() has been moved to xioengine.c */
2008-01-27 12:00:08 +00:00
2008-10-22 00:33:23 +00:00
/* _socat() has been moved to xioengine.c */
2008-01-27 12:00:08 +00:00
2008-10-22 00:33:23 +00:00
/* gettimestamp() has been moved to xiotransfer.c */
2008-01-27 12:00:08 +00:00
2008-10-22 00:33:23 +00:00
/* xioprintblockheader has been moved to xiotransfer.c */
2008-01-27 12:00:08 +00:00
2008-10-22 00:33:23 +00:00
/* xiotransfer has been moved to xiotransfer.c */
2008-01-27 12:00:08 +00:00
2008-10-22 00:33:23 +00:00
/* cv_newline has been moved to xiotransfer.c */
2008-01-27 12:00:08 +00:00
void socat_signal ( int signum ) {
switch ( signum ) {
case SIGQUIT :
case SIGILL :
case SIGABRT :
case SIGBUS :
case SIGFPE :
case SIGSEGV :
case SIGPIPE :
diag_set_int ( ' x ' , 128 + signum ) ; /* in case Error exits for us */
Error1 ( " exiting on signal %d " , signum ) ;
diag_set_int ( ' x ' , 0 ) ; /* in case Error did not exit */
break ;
case SIGTERM :
Warn1 ( " exiting on signal %d " , signum ) ; break ;
case SIGHUP :
case SIGINT :
Notice1 ( " exiting on signal %d " , signum ) ; break ;
}
Exit ( 128 + signum ) ;
}
2008-02-17 13:59:16 +00:00
#if 0
2008-01-27 12:00:08 +00:00
/* this is the callback when the child of an address died */
static int socat_sigchild ( struct single * file ) {
if ( file - > ignoreeof & & ! closing ) {
;
} else {
file - > eof = MAX ( file - > eof , 1 ) ;
closing = 1 ;
}
return 0 ;
}
2008-02-17 13:59:16 +00:00
# endif
2008-01-27 12:00:08 +00:00
static int socat_lock ( void ) {
int lockrc ;
# if 1
if ( ( lockrc = xiolock ( & socat_opts . lock ) ) < 0 ) {
return - 1 ;
}
if ( lockrc = = 0 ) {
havelock = true ;
}
return lockrc ;
# else
if ( socat_opts . lock . lockfile ) {
if ( ( lockrc = xiolock ( socat_opts . lock . lockfile ) ) < 0 ) {
/*Error1("error with lockfile \"%s\"", socat_opts.lock.lockfile);*/
return - 1 ;
}
if ( lockrc ) {
return 1 ;
}
havelock = true ;
/*0 Info1("obtained lock \"%s\"", socat_opts.lock.lockfile);*/
}
if ( socat_opts . lock . waitlock ) {
if ( xiowaitlock ( socat_opts . lock . waitlock , socat_opts . lock . intervall ) ) {
/*Error1("error with lockfile \"%s\"", socat_opts.lock.lockfile);*/
return - 1 ;
} else {
havelock = true ;
/*0 Info1("obtained lock \"%s\"", socat_opts.lock.waitlock);*/
}
}
return 0 ;
# endif
}
static void socat_unlock ( void ) {
if ( ! havelock ) return ;
if ( socat_opts . lock . lockfile ) {
if ( Unlink ( socat_opts . lock . lockfile ) < 0 ) {
Warn2 ( " unlink( \" %s \" ): %s " ,
socat_opts . lock . lockfile , strerror ( errno ) ) ;
} else {
Info1 ( " released lock \" %s \" " , socat_opts . lock . lockfile ) ;
}
}
}
/* this is a callback function that may be called by the newchild hook of xio
*/
static int socat_newchild ( void ) {
havelock = false ;
return 0 ;
}