Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37740288
en ru br
Репозитории ALT

Группа :: Development/Tools
Пакет: tcputils

 Главная   Изменения   Спек   Патчи   Исходники   Загрузить   Gear   Bugs and FR  Repocop 

tcputils-0.6.2/000075500000000000000000000000001207004635500133665ustar00rootroot00000000000000tcputils-0.6.2/INSTALL000064400000000000000000000007611207004635500144230ustar00rootroot00000000000000REQUIREMENTS

You need an ANSI C compiler. Gcc is a nice one that exists for
most platforms.

You need GNU make in order to compile. I think it's too much
work to handle all other make variants with their limitations and
idiosyncrasies. GNU make compiles on almost any Unix machine.
If it doesn't compile on your machine, then my programs probably
won't compile either anyway...



TO COMPILE

Edit Makefile as needed. Type "make" and wait a minute or two.



TO INSTALL

Type "make install".
tcputils-0.6.2/Makefile000064400000000000000000000036431207004635500150340ustar00rootroot00000000000000# Linux RedHat 5.0 has header files that generates warnings when compiling
# with -pedantic, so we leave that out per default.
CC = gcc -Wall #-pedantic
INCLUDE-FLAGS =
COPT = -g -O2
LDFLAGS = ${COPT}
CFLAGS = ${COPT} ${INCLUDE-FLAGS}
RANLIB = ranlib
INSTALL = install -c
MKDIR_P = mkdir -p
# Solaris 2 needs to link with "-lsocket -lnsl". For other unices you might
# need to comment out those libraries.
NETLIBS = -lsocket -lnsl

# Where to install things.
prefix = /usr/local
bindir = ${prefix}/bin
mandir = ${prefix}/man
man1dir = ${mandir}/man1


# ------------------------------------------------------------------
# Things below shouldn't be needed to be changed in order to compile


SUBMAKE = ${MAKE} prefix="${prefix}" CC="${CC}" CFLAGS="${CFLAGS}" AR="${AR}" \
RANLIB="${RANLIB}" INSTALL="${INSTALL}" VPATH="${VPATH}" ${MFLAGS}

IPLIB = ip/libiphelp.a


PROGRAMS = tcpconnect tcplisten tcpbug mini-inetd getpeername
MANUALS1 = tcpconnect.1 tcplisten.1 tcpbug.1 mini-inetd.1 getpeername.1


all: ${IPLIB} ${PROGRAMS}


tcpconnect: tcpconnect.o relay.o
${CC} ${LDFLAGS} $^ ${IPLIB} ${NETLIBS} -o $@
tcplisten: tcplisten.o relay.o
${CC} ${LDFLAGS} $^ ${IPLIB} ${NETLIBS} -o $@
tcpbug: tcpbug.o relay.o
${CC} ${LDFLAGS} $^ ${IPLIB} ${NETLIBS} -o $@
mini-inetd: mini-inetd.o
${CC} ${LDFLAGS} $^ ${IPLIB} ${NETLIBS} -o $@
getpeername: getpeername.o
${CC} ${LDFLAGS} $^ ${NETLIBS} -o $@

${IPLIB}:
cd ip; ${SUBMAKE} all

clean:
${RM} ${PROGRAMS} *.o *~ core
cd ip; ${SUBMAKE} clean

install: install-bin install-man

install-bin: ${bindir} #${PROGRAMS}
${INSTALL} ${PROGRAMS} ${bindir}

install-man: ${man1dir} #${MANUALS1}
${INSTALL} ${MANUALS1} ${man1dir}

install-lib:
cd ip; ${SUBMAKE} install

${bindir}:; ${MKDIR_P} $@
${man1dir}:; ${MKDIR_P} $@


${PROGRAMS}: ${IPLIB}
tcpconnect.o: ip/ip_misc.h relay.h
tcplisten.o: ip/ip_misc.h relay.h
tcpbug.o: ip/ip_misc.h relay.h
mini-inetd.o: ip/ip_misc.h
relay.o: relay.h
getpeername.o:
tcputils-0.6.2/README000064400000000000000000000023561207004635500142540ustar00rootroot00000000000000 -*- text -*-


WHAT IS THIS?

This is version 0.6 of tcputils, a collection of programs to
facilitate TCP programming in shell-scripts. There is also a
small library which makes it somewhat easier to create TCP/IP
sockets.

The latest released version can be found by anonymous FTP to
ftp.lysator.liu.se:pub/unix/tcputils/
(or at URL:ftp://ftp.lysator.liu.se/pub/unix/tcputils/ if you
like that syntax better).
I myself can be reached by email to bellman@lysator.liu.se.


The programs included in this release are:

mini-inetd - small TCP/IP connection dispatcher
tcpbug - TCP/IP connection bugging device
tcpconnect - general TCP/IP client
tcplisten - general TCP/IP server
getpeername - get name of connected TCP/IP peer



BUILDING AND INSTALLING

Read the file INSTALL for instructions.



COPYRIGHT

These programs are released into the public domain. You may do
anything you like with them, including modifying them and selling
the binaries without source for ridiculous amounts of money without
saying who made them originally.

However, I would be happy if you release your works with complete
source for free use.



WARRANTY

You're kidding? You use it, you take the responsibility.



Local variables:
fill-column: 65
End:
tcputils-0.6.2/fionread.c000064400000000000000000000003621207004635500153220ustar00rootroot00000000000000#include <stdio.h>
#include <sys/filio.h>

int
main(int argc,
char **argv)
{
long unread = 0;
int status = 0;

status = ioctl(0, FIONREAD, &unread);
printf("Status: %d Unread: %ld\n", status, unread);

return 0;
}
tcputils-0.6.2/fstat.c000064400000000000000000000014171207004635500146560ustar00rootroot00000000000000#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>

int
main(int argc, char **argv)
{
struct stat f;
int status;

status = fstat(0, &f);
printf("Status: %d errno: %d\n", status, errno);
printf("st_mode: %o\n", f.st_mode);
printf("st_ino: %d\n", f.st_ino);
printf("st_dev: %d\n", f.st_dev);
printf("st_rdev: %d\n", f.st_rdev);
printf("st_nlink: %d\n", f.st_nlink);
printf("st_uid: %d\n", f.st_uid);
printf("st_gid: %d\n", f.st_gid);
printf("st_size: %d\n", f.st_size);
printf("st_atime: %d\n", f.st_atime);
printf("st_mtime: %d\n", f.st_mtime);
printf("st_ctime: %d\n", f.st_ctime);
printf("st_blksize: %d\n", f.st_blksize);
printf("st_blocks: %d\n", f.st_blocks);

return 0;
}
tcputils-0.6.2/getpeername.1000064400000000000000000000014341207004635500157460ustar00rootroot00000000000000.TH GETPEERNAME 1 "1997 April 13"
.SH NAME
getpeername \- get name of connected TCP/IP peer
.SH SYNOPSIS
.B getpeername
.RB [ -n ]
\fR[\fB\-p \fIprotocol\fR]
.SH DESCRIPTION
.B getpeername
prints the IP address and service name (port number) of the
remote peer connected to standard input.
The IP address and the service name are printed on the same line,
separated by one space.
.SH OPTIONS
.TP
.B \-n
Don't translate IP addresses and port numbers to names.
.TP
.B \-p \fIprotocol\fP
Force getpeername to use \fIprotocol\fP as the protocol when
translating port numbers to service names.
\fIProtocol\fP can be \fBtcp\fP and \fBudp\fP.
Normally, getpeername automatically determines what type of
socket it is connected to.
.SH SEE ALSO
.PD
.BR getpeername (3).
.SH BUGS
Only works on IP sockets.
tcputils-0.6.2/getpeername.c000064400000000000000000000045631207004635500160360ustar00rootroot00000000000000#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>


extern int getopt(int, char *const*, const char *);
extern int optind;
extern char *optarg;


char * progname = "getpeername";

int numeric_addresses = 0;
char * protocol = NULL;
int sockno = 0;



void
usage(void)
{
fprintf(stderr, "Usage: %s [-n] [-p protocol]\n", progname);
exit(1);
}


void
fatal(char * msg)
{
fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno));
exit(1);
}


int
main(int argc,
char **argv)
{
int option;
struct sockaddr_in peer;
int peersize = sizeof peer;
char * hostname;
char * portname;
char servbuf[64];

progname = argv[0];

while ((option = getopt(argc, argv, "np:")) != EOF)
{
switch ((char)option)
{
case 'n':
numeric_addresses = 1;
break;
case 'p':
protocol = optarg;
break;
default:
usage();
/* NOTREACHED */
}
}

if (argc - optind > 0)
usage();

if (getpeername(sockno, (struct sockaddr*)&peer, &peersize) < 0)
fatal("can't get peer name");
if (peer.sin_family != AF_INET)
fatal("socket is not an IP socket");

/* Find the type of the socket. Assumes that an INET stream socket
* is TCP and an INET datagram socket is UDP. Can't handle AF_UNIX
* or any other adress families.
*/
if (protocol == NULL)
{
int socktype;
int socktypelen = sizeof socktype;

if (getsockopt(sockno, SOL_SOCKET, SO_TYPE,
(char*)&socktype, &socktypelen) < 0)
fatal("can't get socket type");

switch (socktype)
{
case SOCK_STREAM:
protocol = "tcp";
break;
case SOCK_DGRAM:
protocol = "udp";
break;
default:
fatal("unknown socket type");
/* NOTREACHED */
}
}

hostname = inet_ntoa(peer.sin_addr);
sprintf(servbuf, "%u", ntohs(peer.sin_port));
portname = servbuf;

if (!numeric_addresses)
{
struct hostent *host;
struct servent *service;

host = gethostbyaddr((char*)&peer.sin_addr.s_addr,
sizeof peer.sin_addr.s_addr, AF_INET);
if (host != NULL)
hostname = host->h_name;
service = getservbyport(peer.sin_port, protocol);
if (service != NULL)
portname = service->s_name;
}

printf("%s %s\n", hostname, portname);

return 0;
}
tcputils-0.6.2/ip/000075500000000000000000000000001207004635500137765ustar00rootroot00000000000000tcputils-0.6.2/ip/Makefile000064400000000000000000000006701207004635500154410ustar00rootroot00000000000000OBJECTS = addr.o tcp_connect.o tcp_open.o tcp_listen.o
IPLIB = libiphelp.a

CC = gcc -pedantic -Wall
COPT = -g -O2
CFLAGS = ${COPT}
RANLIB = ranlib

all: ${IPLIB}

${IPLIB}: ${OBJECTS}
${AR} ruv $@ ${OBJECTS}
${RANLIB} $@

clean:
${RM} *.o ${IPLIB} *~ *_pure_*

install:
${INSTALL} ${IPLIB} ${prefix}/lib
${INSTALL} ip_misc.h ${prefix}/include


tcp_connect.o: ip_misc.h
tcp_open.o: ip_misc.h
tcp_listen.o: ip_misc.h
addr.o: ip_misc.h
tcputils-0.6.2/ip/addr.c000064400000000000000000000031031207004635500150510ustar00rootroot00000000000000#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "ip_misc.h"


#define Export


/*
* Fill in ADDR from HOST, SERVICE and PROTOCOL.
* PROTOCOL can be tcp or udp.
* Supplying a null pointer for HOST means use INADDR_ANY.
* Supplying a null pointer for SERVICE, means use port 0, i.e. no port.
*
* Returns negative on errors, zero or positive if everything ok.
*/
Export int
get_inaddr(struct sockaddr_in * addr,
const char * host,
const char * service,
const char * protocol)
{
memset(addr, 0, sizeof *addr);
addr->sin_family = AF_INET;

/*
* Set host part of ADDR
*/
if (host == NULL)
addr->sin_addr.s_addr = INADDR_ANY;
else
{
addr->sin_addr.s_addr = inet_addr(host);
if (addr->sin_addr.s_addr == (unsigned long)-1)
{
struct hostent * hp;

hp = gethostbyname(host);
if (hp == NULL)
return -1;
memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
addr->sin_family = hp->h_addrtype;
}
}

/*
* Set port part of ADDR
*/
if (service == NULL)
addr->sin_port = htons(0);
else
{
char * end;
long portno;

portno = strtol(service, &end, 10);
if (portno > 0 && portno <= 65535
&& end != service && *end == '\0')
{
addr->sin_port = htons(portno);
}
else
{
struct servent * serv;

serv = getservbyname(service, protocol);
if (serv == NULL)
return -1;
addr->sin_port = serv->s_port;
}
}

return 0;
}
tcputils-0.6.2/ip/ip_misc.h000064400000000000000000000014261207004635500155750ustar00rootroot00000000000000#ifndef IP_MISC_H__ALREADY_INCLUDED__
#define IP_MISC_H__ALREADY_INCLUDED__


extern int get_inaddr(struct sockaddr_in* /*addr*/,
const char* /*host*/,
const char* /*service*/,
const char* /*protocol*/);

extern int tcp_connect(const struct sockaddr_in* /*remote*/,
const struct sockaddr_in* /*local*/);

extern int tcp_open(const char* /*remote_host*/,
const char* /*remote_port*/,
const char* /*local_host*/,
const char* /*local_port*/);

extern int tcp_listen_2(const struct sockaddr_in* /*local*/);

extern int tcp_listen(const char* /*interface*/,
const char* /*port*/);

extern char *source_route(int /*type*/,
char** /*hostlist*/,
int /*nhosts*/,
int* /*result_len*/);


#endif /* IP_MISC_H__ALREADY_INCLUDED__ */
tcputils-0.6.2/ip/ip_sourceroute.c000064400000000000000000000010111207004635500172020ustar00rootroot00000000000000/*
*/

#include <netinet/ip.h>

#include "ip_misc.h"


#define Export


Export char *
source_route(int type,
char ** hostlist,
int nhosts;
int * result_len)
{
char * option;


if (type != IPOPT_LSRR && type != IPOPT_SSRR) {
errno = EINVAL;
return NULL;
}

optlen = nhosts * 4 + IPOPT_MINOFF;
option = malloc(optlen);
if (option == NULL)
return NULL;
option[0] = type;
option[1] = optlen;
option[2] = IPOPT_MINOFF;
h = &option[IPOPT_MINOFF - 1];

tcputils-0.6.2/ip/tcp_connect.c000064400000000000000000000016441207004635500164460ustar00rootroot00000000000000#include <stddef.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "ip_misc.h"


#define Export


/*
* Open a TCP connection to REMOTE. Bind the local port to
* LOCAL, if set.
* Returns the file descriptor for the connection, or negative
* on errors.
*/
Export int
tcp_connect(const struct sockaddr_in * remote,
const struct sockaddr_in * local)
{
int s;

s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s < 0)
return -1;
if (local && bind(s, (struct sockaddr *)local, sizeof *local) < 0)
{ int saved_errno = errno;
close(s);
errno = saved_errno;
return -1;
}
if (connect(s, (struct sockaddr *)remote, sizeof *remote) < 0)
{ int saved_errno = errno;
close(s);
errno = saved_errno;
return -1;
}
return s;
}
tcputils-0.6.2/ip/tcp_listen.c000064400000000000000000000021771207004635500163150ustar00rootroot00000000000000#include <stddef.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "ip_misc.h"


#define Export


/*
* Open a TCP socket listening on address LOCAL.
* Returns the file descriptor for the socket, or negative
* on errors.
*/
Export int
tcp_listen_2(const struct sockaddr_in * local)
{
int s;
struct protoent * proto;

proto = getprotobyname("tcp");
if (proto == NULL)
return -1;
s = socket(PF_INET, SOCK_STREAM, proto->p_proto);
if (s < 0)
return -1;
{
int yes = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof yes);
}
if (bind(s, (struct sockaddr *)local, sizeof *local) < 0)
{
close(s);
return -1;
}
if (listen(s, 256) < 0)
{
close(s);
return -1;
}

return s;
}



Export int
tcp_listen(const char * interface,
const char * port)
{
int s;
struct sockaddr_in server;

if (get_inaddr(&server, interface, port, "tcp") < 0)
return -1;
s = tcp_listen_2(&server);
return s;
}
tcputils-0.6.2/ip/tcp_open.c000064400000000000000000000045071207004635500157570ustar00rootroot00000000000000#include <stddef.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "ip_misc.h"


#define Export



/*
* Open a TCP connection to port REMOTE_PORT on host REMOTE_HOST.
* If LOCAL_HOST is not NULL, the local end of the connection is
* bound to that address. If LOCAL_PORT is not NULL, the local
* end of the connection is bound to that port.
* Hosts may be given as either a numeric IP address or as a host
* names. Ports may be given as either a decimal port number, or
* as a symbolic service name.
*
* Returns the file descriptor for the connection, or negative on
* errors.
*/
Export int
tcp_open(const char *remote_host,
const char *remote_port,
const char *local_host,
const char *local_port)
{
struct sockaddr_in server;
struct sockaddr_in local;
struct hostent * he;
int s;

#define ERRORRET(n) do { int e=errno;close(s);errno=e;return (n);} while (0)

if (remote_host == NULL || remote_port == NULL)
{
errno = EINVAL;
return -1;
}

if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
return -1;
if (local_host || local_port)
{
if (get_inaddr(&local, local_host, local_port, "tcp") < 0)
ERRORRET(-1);
if (bind(s, (struct sockaddr*)&local, sizeof local) < 0)
ERRORRET(-1);
}

/* Get port */
if (get_inaddr(&server, NULL, remote_port, "tcp") < 0)
ERRORRET(-1);

/* Check for numerical IP address */
server.sin_addr.s_addr = inet_addr(remote_host);
if (server.sin_addr.s_addr != (unsigned long)-1)
{
if (connect(s, (struct sockaddr*)&server, sizeof server) < 0)
ERRORRET(-1);
return s;
}

/* Not numerical address, then it should be a host name.
* gethostbyname() it and try all the hosts addresses.
*/
if ((he = gethostbyname(remote_host)) == NULL)
ERRORRET(-1);
assert(he->h_addrtype == AF_INET);
assert(he->h_length == sizeof server.sin_addr.s_addr);

server.sin_family = he->h_addrtype;
{
char **a = he->h_addr_list;
while (*a)
{
memcpy(&server.sin_addr, *a, sizeof server.sin_addr);
if (connect(s, (struct sockaddr*)&server, sizeof server) >= 0)
return s;
a++;
}
}
ERRORRET(-1);
}
tcputils-0.6.2/mini-inetd.1000064400000000000000000000016031207004635500155050ustar00rootroot00000000000000.TH MINI-INETD 1 "1997 April 13"
.SH NAME
mini-inetd \- small TCP/IP connection dispatcher
.SH SYNOPSIS
.B mini-inetd
.RB [ -d ]
\fR[\fB-m \fImaxconnections\fR]
.I \fR[\fPlocaladdr\fB:\fP\fR]\fPport
.I program
[\fIargv0 argv1\fR ...]
.SH DESCRIPTION
.B mini-inetd
listens for TCP/IP connections on \fIport\fP.
For each connection, \fIprogram\fP is started
with standard input and standard output connected to the socket.
If \fIlocaladdr\fP is given, mini-inetd only listens for
connections on the interface specified by that hostname or IP
address,
otherwise, it listens to all IP interfaces on the machine.
.SH OPTIONS
.TP
.B \-d
Debug...
.TP
.B \-m \fImaxconnections\fP
Exit after \fImaxconnections\fP connections has been handled.
.SH SEE ALSO
.PD
.BR tcpconnect (1),
.BR tcplisten (1),
.BR inetd (1m).
.SH BUGS
The names of the options are not yet finalized, and may change
at a future release.
tcputils-0.6.2/mini-inetd.c000064400000000000000000000054131207004635500155720ustar00rootroot00000000000000#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <limits.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#include "ip/ip_misc.h"


extern char ** environ;
extern int getopt(int, char *const*, const char *);
extern int optind;
extern char * optarg;


char * progname = "mini-inetd";
int debug = 0;
int max_connections = 0;


static void
usage()
{
fprintf(stderr,
"Usage: %s [-d] [-m max] port program [argv0 argv1 ...]\n",
progname);
exit(1);
}


static void
vfatal(const char *fmt, va_list args)
{
fputs(progname, stderr);
fputs(": ", stderr);
vfprintf(stderr, fmt, args);
putc('\n', stderr);
exit(1);
}


static void
fatal(const char *fmt, ...)
{
va_list args;

va_start(args, fmt);
vfatal(fmt, args);
va_end(args);
}



static void
reap_children(int signo)
{
pid_t child;
int status;
char buf[64 + sizeof(long) * CHAR_BIT];

while ((child = waitpid(-1, &status, WNOHANG)) > (pid_t)0)
{
if (debug)
{
sprintf(buf, "Child %ld died\n", (long)child);
write(2, buf, strlen(buf));
}
}
signal(signo, &reap_children);
}



int
main(int argc, char **argv)
{
int sd;
pid_t child;
int option;
char *host;
char *port;

while ((option = getopt (argc, argv, "dm:")) != EOF)
{
switch ((char)option)
{
case 'd':
debug++;
break;
case 'm':
max_connections = atoi(optarg);
break;
default:
usage();
/* NOTREACHED */
}
}

if (argc - optind < 2)
usage();

port = strrchr(argv[optind], ':');
if (port != NULL) {
*(port++) = '\0';
host = argv[optind];
} else {
port = argv[optind];
host = NULL;
}
if ((sd = tcp_listen(host, port)) < 0)
fatal("Can't listen to port %s: %s", argv[optind], strerror(errno));

/* Reap children */
#if defined(SIGCHLD)
signal(SIGCHLD, &reap_children);
#elif defined(SIGCLD)
signal(SIGCLD, &reap_children);
#endif

while (1)
{
struct sockaddr_in them;
int len = sizeof them;
int ns = accept(sd, (struct sockaddr*)&them, &len);
if (ns < 0) {
if (errno == EINTR)
continue;
fatal("Accept failed: %s", strerror(errno));
}
switch (child = fork()) {
case -1:
perror("Can't fork");
break;
case 0:
/* Child */
close(sd);
dup2(ns, 0);
dup2(ns, 1);
execve(argv[optind+1], argv+optind+2, environ);
fatal("Can't start %s: %s", argv[optind+1], strerror(errno));
default:
/* Parent */
if (debug)
fprintf(stderr, "Forked child %ld\n", (long)child);
close(ns);
break;
}
if (max_connections > 0 && --max_connections <= 0)
break;
}

return 0;
}

tcputils-0.6.2/relay.c000064400000000000000000000106711207004635500146530ustar00rootroot00000000000000#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#if defined(__hpux__) || defined(__linux__)
# include <sys/ioctl.h>
#else
# include <sys/filio.h>
#endif
#include <sys/socket.h>

#include "relay.h"


#define Export


#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))


/*
* Estimate how many bytes are available for reading on a file descriptor.
*/
static long
available_bytes(int fd)
{
long nbytes;
struct stat sb;
off_t pos;

/*
* Some Unices don't support the FIONREAD ioctl on regular files.
* They don't even return an error, but says there are zero bytes
* to be read. We then try to fstat() the file descriptor to see
* how big the file is, and try to determine at what offset the
* file pointer is at now. That doesn't work always either...
*/

if (ioctl(fd, FIONREAD, &nbytes) < 0 || nbytes == 0)
{
if (fstat(fd, &sb) < 0)
return -1;
errno = 0;
pos = lseek(fd, 0, SEEK_CUR);
if ((pos < 0 && errno != 0) || !S_ISREG(sb.st_mode))
pos = 0;
nbytes = sb.st_size - pos;
}
return nbytes;
}



/*
* Wait for data to arrive on any of the source file descriptors in
* RELAYS, read all available data, and write to respective dest
* file descriptors. TIMEOUT is the maximum time to wait, or a nil
* pointer to never time out. For each read() done, the function
* CALLBACK is called. Note that CALLBACK may be called more than
* once for each file descriptor if much data is available.
* NRELAYS is the number of elements in RELAYS.
*
* If the 'readerror' field is non-zero for a relay, no read will be
* attempted from the source file descriptor of that relay.
* If the 'writerror' field is non-zero for a relay, no write will be
* attempted to the dest file descriptor of that relay, but the source
* descriptor will still be drained from any available data.
*
* If end-of-file is reached on the source of a relay, the corresponding
* destination will be shutdown() for writing, thus causing the other
* end to see a end-of-file.
* If a write error occurs on the destination of a relay, the source
* of that relay will be shutdown() for reading, causing the other end
* to get errors when trying to write more data to us.
* Note that the SIGPIPE signal should be ignored, or possibly caught,
* by the caller, or the process will die when a receiver closes its
* end for receiving.
*
* Returns the number of file descriptor read from, or negative on error.
*/
Export int
relay_once(struct relay * relays,
int nrelays,
struct timeval * timeout,
int (*callback)(struct relay*, char*, size_t)
)
{
int maxfd;
fd_set readset;
int i;
int nfds;
int nerrors = 0;

FD_ZERO(&readset);
maxfd = 0;
for (i = nrelays - 1 ; i >= 0 ; i--)
{
if (!relays[i].readerror) {
FD_SET(relays[i].source, &readset);
if (relays[i].source > maxfd)
maxfd = relays[i].source;
}
}

nfds = select(maxfd+1, &readset, (fd_set*)NULL, (fd_set*)NULL, timeout);
if (nfds <= 0) {
if (errno != EINTR)
return nfds;
else
return 0;
}

for (i = nrelays - 1 ; i >= 0 ; i--)
{
if (FD_ISSET(relays[i].source, &readset))
{
long unread = available_bytes(relays[i].source);
do
{
char buffer[8192];
int bytes_read = read(relays[i].source, buffer, sizeof buffer);

if (bytes_read < 0) {
relays[i].readerror = errno;
nerrors++;
break;
}
unread -= bytes_read;
if (bytes_read == 0) {
relays[i].readerror = -1;
shutdown(relays[i].dest, 1);
nerrors++;
}
if (callback)
(*callback)(&relays[i], buffer, bytes_read);
if (!relays[i].writeerror && bytes_read > 0) {
int written = write(relays[i].dest, buffer, bytes_read);
if (written < 0) {
relays[i].writeerror = errno;
shutdown(relays[i].source, 0);
nerrors++;
break;
}
}
} while (unread > 0);
}
}

return nerrors ? -nerrors : nfds;
}



/*
* Call relay_once() until end-of-file has been reached on all sources.
* No time limit.
*/
Export int
relay_all(struct relay * relaylist,
int nrelays,
int (*callback)(struct relay*, char*, size_t))
{
int nclosed = 0;
do
{
int status = relay_once(relaylist, nrelays, NULL, callback);
if (status < 0)
nclosed += -status;
} while (nclosed < nrelays);

return 0;
}
tcputils-0.6.2/relay.h000064400000000000000000000010701207004635500146510ustar00rootroot00000000000000struct relay {
/* IN: file descriptor to read from */
int source;
/* IN: file descriptor to read to */
int dest;
/* IN+OUT: errno for failed read. -1 if EOF reached. */
int readerror;
/* IN+OUT: errno for failed write. EPIPE if receiver is dead. */
int writeerror;
/* IN: for private use by the callback function */
void * userdata;
};


extern int relay_once(struct relay *,
int,
struct timeval *,
int (*)(struct relay*, char*, size_t));
extern int relay_all(struct relay *,
int,
int (*)(struct relay*, char*, size_t));
tcputils-0.6.2/relay1.c000064400000000000000000000031171207004635500147310ustar00rootroot00000000000000#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/filio.h>
#include <sys/socket.h>


#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))


int
relay(int fd1,
int fd2,
int (*callback)(char prefix, char *data, size_t nbytes))
{
fd_set readset;
int nfds, len;
char buffer[8192];
int fd1_eof = 0;
int fd2_eof = 0;

while (!fd1_eof || !fd2_eof)
{
/* Setup file descriptor set */
FD_ZERO(&readset);
if (!fd1_eof)
FD_SET(fd1, &readset);
if (!fd2_eof)
FD_SET(fd2, &readset);

nfds = select(MAX(fd1, fd2)+1,
&readset, NULL, NULL, NULL);

/* error? */
if (nfds < 0)
{
if (errno == EINTR)
continue;
return -1;
}

/* timeout? */
if (nfds == 0)
continue;

if (FD_ISSET(fd1, &readset))
{
long unread;
ioctl(fd1, FIONREAD, &unread);
do
{
if ((len = read(fd1, buffer, sizeof buffer)) < 0)
{
return -1;
}
unread -= len;

/* remote server close? */
if (len == 0)
{
shutdown(fd2, 1);
fd1_eof = 1;
}
callback('>', buffer, len);
write(fd2, buffer, len);
} while (unread > 0);
}

if (FD_ISSET(fd2, &readset))
{
long unread;
ioctl(fd2, FIONREAD, &unread);
do
{
if ((len = read(fd2, buffer, sizeof buffer)) < 0)
{
return -1;
}
unread -= len;

/* remote client close? */
if (len == 0)
{
shutdown(fd1, 1);
fd2_eof = 1;
}
callback('<', buffer, len);
write(fd1, buffer, len);
} while (unread > 0);
}

}

return 0;
}
tcputils-0.6.2/tcpbug.1000064400000000000000000000033731207004635500147420ustar00rootroot00000000000000.TH TCPBUG 1 "1997 April 13"
.SH NAME
tcpbug \- TCP/IP connection bugging device
.SH SYNOPSIS
.B tcpbug
.RB [ -cx ]
.RB [ -btT ]
.I local-port
.I remote-host
.I remote-port
.SH DESCRIPTION
.B tcpbug
forwards a TCP/IP connection to port \fIlocal-port\fP on the
local machine to the port \fIremote-port\fP on \fIremote-host\fP
while spying on the connection and writing all data passing
through to standard output.
All data coming from the client is printed with a greater than
sign (\fB>\fP) first on each line,
and all data coming from the server is printed with a less than
sign (\fB<\fP) first on each line.
Any byte offsets and time-stamps are printed before the greater
than or less than sign,
and are separated from each other by a colon (\fB:\fP).
.SH OPTIONS
.TP
.B \-b
Print the offset of the first byte in the stream for each line.
.TP
.B \-c
Display bytes as individual characters.
Printable characters are displayed directly,
some control characters appear as C-language escapes
.RB ( \en ", " \er ", " \et " et.c),"
while others appear as 3-digit octal numbers.
This should be similar to the -c switch of
.BR od (1).
.TP
.B \-t
Print the time at which the data was received for each line.
The time is the number of seconds and microseconds,
separated by a decimal point
.RB ( . ),
since 00:00 UTC, January 1, 1970, as reported by gettimeofday().
.TP
.B \-T
Print the time at which the data was received for each line.
The time is the number of seconds and microseconds,
separated by a decimal point
.RB ( . ),
since the connections were established.
.TP
.B \-x
Display each byte as a two digit hexadecimal number.
.SH SEE ALSO
.PD
.BR tcpconnect (1),
.BR tcplisten (1),
.BR od (1).
.SH BUGS
The names of the options are not yet finalized, and may change
at a future release.
tcputils-0.6.2/tcpbug.c000064400000000000000000000206071207004635500150230ustar00rootroot00000000000000/*
* tcpbug.c -- Accept a TCP/IP connection, and relay it to somewhere
* else, while spying on the connection
*
*
* This program is in the public domain. You may do anything
* you like with it.
*
*
* Author: Thomas Bellman
* Lysator Computer Club
* LinkЖping University
* Sweden
* email: Bellman@Lysator.LiU.SE
*
*
* Any opinions expressed in this code are the author's PERSONAL opinions,
* and does NOT, repeat NOT, represent any official standpoint of Lysator,
* even if so stated.
*/


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <locale.h>
#include <limits.h>

#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "ip/ip_misc.h"
#include "relay.h"


extern int getopt(int, char *const*, const char *);
extern int optind;
extern char *optarg;




char * progname = "tcpbug";
int quiet_mode = 0;

int linewidth = -1;
/* Non-zero if a bytecount should be logged */
int bug_bytecount = 0;
/* Non-zero if logged data should be timestamped */
int bug_timestamp = 0;
/* Non-zero if logged data should be timestamped relative to the
establishing of the connection */
int bug_relative_timestamp= 0;


struct bugstat {
/* The prefix character */
char prefix;
/* Where to send bugged data */
FILE * logfile;
/* Bytes passed this way */
unsigned long nbytes;
/* Function to do actual printing of bugged data */
int (*bugfun)(struct relay *, char *, size_t);
/* Time when bugger() was called */
struct timeval time;
/* Time when the connection was established */
struct timeval conntime;
};



void
log(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (!quiet_mode)
vfprintf(stderr, fmt, args);
va_end(args);
}


void
fatal(char * msg)
{
fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno));
exit(1);
}



#define COLON() (things_printed++ ? putc(':', bs->logfile),++*pos : 0)

int
prefix(struct relay * rel,
int eof,
int * pos)
{
struct bugstat * bs = rel->userdata;
int things_printed = 0;

if (bug_bytecount) {
char buf[sizeof bs->nbytes * CHAR_BIT];
COLON();
sprintf(buf, "%04lx", bs->nbytes);
fputs(buf, bs->logfile);
*pos += strlen(buf);
}
if (bug_timestamp) {
char buf[64];
COLON();
sprintf(buf, "%ld.%06ld", bs->time.tv_sec, bs->time.tv_usec);
fputs(buf, bs->logfile);
*pos += strlen(buf);
}
if (bug_relative_timestamp) {
char buf[64];
struct timeval diff;
COLON();
diff.tv_sec = bs->time.tv_sec - bs->conntime.tv_sec;
diff.tv_usec = bs->time.tv_usec - bs->conntime.tv_usec;
if (diff.tv_usec < 0)
diff.tv_usec += 1000000, diff.tv_sec -= 1;
sprintf(buf, "%ld.%06ld", diff.tv_sec, diff.tv_usec);
fputs(buf, bs->logfile);
*pos += strlen(buf);
}
putc(bs->prefix, bs->logfile);
if (eof)
fputs("EOF\n", bs->logfile);
else
putc(' ', bs->logfile);

return 0;
}



int
bugger(struct relay * rel,
char * data,
size_t datalen)
{
struct bugstat * bs = rel->userdata;
int pos = 0;

gettimeofday(&bs->time, NULL);
if (datalen == 0) {
prefix(rel, -1, &pos);
return 0;
}

bs->bugfun(rel, data, datalen);
fflush(bs->logfile);

return 0;
}



int
charbugger(struct relay * rel,
char * data,
size_t datalen)
{
int pos = 0;
struct bugstat *bs = rel->userdata;

for ( ; datalen > 0 ; datalen--, data++, bs->nbytes++)
{
register int c = (unsigned char)*data;

if (pos == 0)
prefix(rel, 0, &pos);

if (isprint(c)) {
putc(' ', bs->logfile);
putc(' ', bs->logfile);
putc(c, bs->logfile);
} else if (c == '\n') {
putc(' ', bs->logfile);
putc('\\', bs->logfile);
putc('n', bs->logfile);
} else if (c == '\r') {
putc(' ', bs->logfile);
putc('\\', bs->logfile);
putc('r', bs->logfile);
} else if (c == '\b') {
putc(' ', bs->logfile);
putc('\\', bs->logfile);
putc('b', bs->logfile);
} else if (c == '\f') {
putc(' ', bs->logfile);
putc('\\', bs->logfile);
putc('f', bs->logfile);
} else if (c == '\t') {
putc(' ', bs->logfile);
putc('\\', bs->logfile);
putc('t', bs->logfile);
} else {
putc('0' + (c>>6 & 7), bs->logfile);
putc('0' + (c>>3 & 7), bs->logfile);
putc('0' + (c>>0 & 7), bs->logfile);
}
putc(' ', bs->logfile);
pos += 4;

if (linewidth > 0 && pos >= linewidth) {
putc('\n', bs->logfile);
pos = 0;
}
}
if (pos != 0)
putc('\n', bs->logfile);

return 0;
}



int
hexbugger(struct relay * rel,
char * data,
size_t datalen)
{
int pos = 0;
struct bugstat *bs = rel->userdata;
static char *hexdigits = "0123456789abcdef";

for ( ; datalen > 0 ; datalen--, data++, bs->nbytes++)
{
register int c = (unsigned char)*data;

if (pos == 0)
prefix(rel, 0, &pos);

putc(hexdigits[c>>4 & 0xf], bs->logfile);
putc(hexdigits[c>>0 & 0xf], bs->logfile);
putc(' ', bs->logfile);
pos += 3;

if (linewidth > 0 && pos >= linewidth) {
putc('\n', bs->logfile);
pos = 0;
}
}
if (pos != 0)
putc('\n', bs->logfile);

return 0;
}



int
linebugger(struct relay * rel,
char * data,
size_t datalen)
{
int pos = 0;
struct bugstat *bs = rel->userdata;

for ( ; datalen > 0 ; datalen--, data++, bs->nbytes++)
{
register int c = (unsigned char)*data;

if (pos == 0)
prefix(rel, 0, &pos);

putc(c, bs->logfile); pos++;
if (c == '\n') {
pos = 0;
}
#if 0
if (linewidth > 0 && pos >= linewidth) {
putc('\n', bs->logfile);
pos = 0;
}
#endif
}
if (pos != 0)
putc('\n', bs->logfile);

return 0;
}



void
usage ()
{
fprintf(stderr,
"usage: %s [-cx] [-btT] [-w linewidth] my-port server-host server-port\n",
progname);
fprintf(stderr,
"\t%s is a program that bugs a TCP/IP connection. It waits\n"
"\tfor connections on a port that you specify, and then connects\n"
"\tto a server on a machine and a port you specify. It then\n"
"\tprints out everything that is sent on the connection to\n"
"\tstdout.\n", progname
);
exit(1);
}


int
main (argc, argv)
int argc;
char **argv;
{
struct sockaddr_in cliaddr;
int cliaddrlen = sizeof cliaddr;
int listen_fd;
int client_fd;
int server_fd;
int option;
int (*bugfun)(struct relay *, char *, size_t) = NULL;

progname = argv[0];

setlocale(LC_CTYPE, "");

while ((option = getopt (argc, argv, "cxw:tTb")) != EOF)
{
switch ((char)option)
{
case 'c':
if (bugfun != NULL)
usage();
bugfun = charbugger;
if (linewidth < 0)
linewidth = 72;
break;
case 'x':
if (bugfun != NULL)
usage();
bugfun = hexbugger;
if (linewidth < 0)
linewidth = 72;
break;
case 'w':
linewidth = atoi(optarg);
break;
case 't':
bug_timestamp = 1;
break;
case 'T':
bug_relative_timestamp = 1;
break;
case 'b':
bug_bytecount = 1;
break;
default:
usage();
/* NOTREACHED */
}
}
if (argc - optind != 3)
usage();

if (bugfun == NULL)
bugfun = linebugger;

listen_fd = tcp_listen(NULL, argv[optind]);
if (listen_fd < 0)
fatal("can't listen to port");
client_fd = accept(listen_fd, (struct sockaddr *)&cliaddr, &cliaddrlen);
if (client_fd < 0)
fatal("accept failed");
log("[Connection from %s port %d]\n",
inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
close(listen_fd);
server_fd = tcp_open(argv[optind+1], argv[optind+2], NULL, NULL);
if (server_fd < 0)
fatal("can't connect to server");

{
struct relay fds[2];
struct bugstat buggers[2];
struct timeval now;

gettimeofday(&now, NULL);
signal(SIGPIPE, SIG_IGN);

fds[0].source = client_fd;
fds[0].dest = server_fd;
fds[0].readerror = 0;
fds[0].writeerror = 0;
fds[0].userdata = &buggers[0];
buggers[0].nbytes = 0;
buggers[0].prefix = '>';
buggers[0].logfile = stdout;
buggers[0].bugfun = bugfun;
buggers[0].conntime = now;

fds[1].source = server_fd;
fds[1].dest = client_fd;
fds[1].readerror = 0;
fds[1].writeerror = 0;
fds[1].userdata = &buggers[1];
buggers[1].nbytes = 0;
buggers[1].prefix = '<';
buggers[1].logfile = stdout;
buggers[1].bugfun = bugfun;
buggers[1].conntime = now;

relay_all(fds, 2, bugger);
}

return 0;
}
tcputils-0.6.2/tcpconnect.1000064400000000000000000000023711207004635500156130ustar00rootroot00000000000000.TH TCPCONNECT 1 "1997 April 13"
.SH NAME
tcpconnect \- general TCP/IP client
.SH SYNOPSIS
.B tcpconnect
.RB [ -irv ]
\fR[\fB\-l \fIlocaladdr\fR]
.I host
.I port
.SH DESCRIPTION
.B tcpconnect
creates a TCP/IP connection to a server running on the machine
.IR host ,
listening to port
.IR port .
It then reads standard input and sends to the remote server, and
data received from the server is printed to standard output.
When end-of-file is reached on both standard input and the TCP/IP
connection,
.B tcpconnect
terminates.
.SH OPTIONS
.TP
.B \-i
Terminate at end-of-file on standard input; don't wait for the
server to close the connection.
.TP
.B \-r
Terminate when the remote server closes the connection; don't
wait for end-of-file on standard input.
.TP
.B \-v
Verbose mode.
Prints a message to standard error when the connection has been
established.
.TP
.B \-l \fIaddr\fB:\fIport
Bind the local end-point of the connection to IP address
.IR addr ,
TCP port
.IR port .
Either the IP address or the port, but not both, may be left out,
meaning that the operating system gets to choose that part by
itself.
.SH SEE ALSO
.PD
.BR tcplisten (1),
.BR telnet (1),
.BR tcpbug (1).
.SH BUGS
The names of the options are not yet finalized, and may change
at a future release.
tcputils-0.6.2/tcpconnect.c000064400000000000000000000062551207004635500157020ustar00rootroot00000000000000/*
* tcpconnect.c
* Connect to a TCP/IP port, send standard input to that
* connection, and print messages from that connection on
* standard output.
*
*
* This program is in the public domain. You may do anything
* you like with it.
*
*
* Author: Thomas Bellman
* Lysator Computer Club
* LinkЖping University
* Sweden
* email: Bellman@Lysator.LiU.Se
*
*
* Any opinions expressed in this code are the author's PERSONAL opinions,
* and does NOT, repeat NOT, represent any official standpoint of Lysator,
* even if so stated.
*/


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <signal.h>

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "ip/ip_misc.h"
#include "relay.h"


extern int getopt(int, char *const*, const char *);
extern int optind;
extern char *optarg;


char * progname = "tcpconnect";
int verbose = 0;


void
usage(void)
{
fprintf(stderr, "Usage: %s [-irv] [-l addr:port] host port\n", progname);
exit(1);
}


void
log(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (verbose)
vfprintf(stderr, fmt, args);
va_end(args);
}


void
fatal(char * msg)
{
fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno));
exit(1);
}



int
main (int argc,
char ** argv)

{
int tcp;
int option;
int close_on_stdin_eof = 0;
int close_on_remote_eof = 0;
char * localaddr = NULL;
char * localport = NULL;

progname = argv[0];
while ((option = getopt(argc, argv, "irvl:q")) != EOF)
{
switch ((char)option)
{
case 'i':
close_on_stdin_eof = 1;
break;
case 'r':
close_on_remote_eof = 1;
break;
case 'l':
localaddr = optarg;
if ((localport = strrchr(localaddr, ':')) != NULL) {
if (localaddr == localport)
localaddr = NULL;
*localport = '\0';
localport++;
}
break;
case 'v':
verbose = 1;
break;
default:
usage();
/* NOTREACHED */
}
}

if (argc - optind != 2)
usage();

{
struct sockaddr_in server;
int serversize = sizeof server;
struct relay fds[2];
int nclosed = 0;

tcp = tcp_open(argv[optind], argv[optind+1], localaddr, localport);
if (tcp < 0)
fatal("Can't connect to server");
if (getpeername(tcp, (struct sockaddr*)&server, &serversize) >= 0)
log("[Connected to %s port %d]\n",
inet_ntoa(server.sin_addr), ntohs(server.sin_port));
else
log("[Connected to unknown server]\n");

fds[0].source = 0;
fds[0].dest = tcp;
fds[0].writeerror = 0;
fds[0].readerror = 0;

fds[1].source = tcp;
fds[1].dest = 1;
fds[1].writeerror = 0;
fds[1].readerror = 0;

signal(SIGPIPE, SIG_IGN);
do {
int status = relay_once(fds, 2, NULL, NULL);
if (status < 0)
nclosed += -status;
if (close_on_stdin_eof &&
(fds[0].readerror || fds[1].writeerror))
{
break;
}
if (close_on_remote_eof &&
(fds[1].readerror || fds[0].writeerror))
{
break;
}
} while (nclosed < 2);
log("[Connection closed]\n");
}

return 0;
}
tcputils-0.6.2/tcplisten.1000064400000000000000000000021521207004635500154550ustar00rootroot00000000000000.TH TCPCONNECT 1 "1997 April 13"
.SH NAME
tcplisten \- general TCP/IP server
.SH SYNOPSIS
.B tcplisten
.RB [ -irv ]
.RI [ localaddr ]
.I port
.SH DESCRIPTION
.B tcplisten
waits for a TCP/IP connection on
.IR port .
If a
.I localaddr
parameter is given,
.B tcplisten
will bind to that IP address. Otherwise
.B tcplisten
will accept connections to any of the local machines IP
addresses.
Data received from the client is printed on standard output, and
data read from standard input is sent to the client.
When end-of-file is reached on both standard input and the TCP/IP
connection,
.B tcplisten
terminates.
.SH OPTIONS
.TP
.B \-i
Terminate at end-of-file on standard input; don't wait for the
client to close the connection.
.TP
.B \-r
Terminate when the remote client closes the connection; don't
wait for end-of-file on standard input.
.TP
.B \-v
Verbose mode.
Prints a message to standard error about the origins (host and
port) of the client.
.SH SEE ALSO
.PD
.BR tcpconnect (1),
.BR telnet (1),
.BR mini-inetd (1),
.BR tcpbug (1).
.SH BUGS
The names of the options are not yet finalized, and may change
at a future release.
tcputils-0.6.2/tcplisten.c000064400000000000000000000062331207004635500155430ustar00rootroot00000000000000/*
* tcplisten.c
* Wait for a connection to a TCP/IP port, send standard input
* to that connection, and print messages from that connection
* on standard output.
*
*
* This program is in the public domain. You may do anything
* you like with it.
*
*
* Author: Thomas Bellman
* Lysator Computer Club
* LinkЖping University
* Sweden
* email: Bellman@Lysator.LiU.Se
*
*
* Any opinions expressed in this code are the author's PERSONAL opinions,
* and does NOT, repeat NOT, represent any official standpoint of Lysator,
* even if so stated.
*/


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <signal.h>

#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "ip/ip_misc.h"
#include "relay.h"


extern int getopt(int, char *const*, const char *);
extern int optind;



char * progname = "tcplisten";
int verbose = 0;


void
usage(void)
{
fprintf(stderr, "Usage: %s [-irv] [localaddr] port\n", progname);
exit(1);
}


void
log(const char *fmt, ...)
{
va_list args;
if (!verbose)
return;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}


void
fatal(char * msg)
{
fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno));
exit(1);
}




int
main (int argc,
char ** argv)

{
int lp;
int option;
int close_on_stdin_eof = 0;
int close_on_remote_eof = 0;

progname = argv[0];
while ((option = getopt(argc, argv, "irv")) != EOF)
{
switch ((char)option)
{
case 'i':
close_on_stdin_eof = 1;
break;
case 'r':
close_on_remote_eof = 1;
break;
case 'v':
verbose = 1;
break;
default:
usage();
/* NOTREACHED */
}
}

if (argc - optind == 1)
lp = tcp_listen(NULL, argv[optind]);
else if (argc - optind == 2)
lp = tcp_listen(argv[optind], argv[optind+1]);
else
usage();
/* Some compilers might complain that 'lp' might be used uninitialized
* here, but that's because they don't realize that usage() doesn't
* return. */
if (lp < 0)
fatal("Unable to listen to port");

{
int client;
struct sockaddr_in cliaddr;
int cliaddrsize = sizeof cliaddr;
struct relay fds[2];
int nclosed = 0;

client = accept(lp, (struct sockaddr*)&cliaddr, &cliaddrsize);
if (client < 0)
fatal("Accept failed");
close(lp);
log("[Connection from %s port %d]\n",
inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));

fds[0].source = 0;
fds[0].dest = client;
fds[0].writeerror = 0;
fds[0].readerror = 0;

fds[1].source = client;
fds[1].dest = 1;
fds[1].writeerror = 0;
fds[1].readerror = 0;

signal(SIGPIPE, SIG_IGN);
do {
int status = relay_once(fds, 2, NULL, NULL);
if (status < 0)
nclosed += -status;
if (close_on_stdin_eof &&
(fds[0].readerror || fds[1].writeerror))
{
break;
}
if (close_on_remote_eof &&
(fds[1].readerror || fds[0].writeerror))
{
break;
}
} while (nclosed < 2);
log("[Connection closed]\n");
}

return 0;
}
tcputils-0.6.2/version.h000064400000000000000000000000511207004635500152200ustar00rootroot00000000000000char *tcputils_version = "tcputils 0.6";
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin