/*
 * tcpsend [-t timeout] host port [files]
 *
 * open a TCP/IP connection to port on host and send files
 *  Super lightweight LPR ???
 * tcpsend.c,v 1.1 2000/10/14 21:11:23 papowell Exp
 */

#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

char *Prog = "???";

char *msg[] = {
	"use: %s [-t timeout] host port [files]",
	"  -t timeout  - try connecting for timeout seconds",
	0
};

int max_try = 10;

void do_send( int sock, int fd, char *name );
void Set_linger( int sock, int n );

void usage(void)
{
	int i;
	fprintf( stderr, msg[0], Prog );
	fprintf( stderr, "\n");
	for( i = 1; msg[i]; ++i ){
		fprintf( stderr, "%s\n", msg[i] );
	}
	exit(1);
}

char buffer[10*1024];

int main( int argc, char **argv )
{
	int n, try;
	int sock;	         /* socket */
	char *s, *host, *port;
	struct sockaddr_in dest_sin;     /* inet socket address */
	struct hostent *host_ent = 0;

	(void)signal( SIGPIPE, SIG_IGN );
	if( argv[0] ) Prog = argv[0];
	if( (s = strrchr(Prog,'/')) ){
		Prog = s+1;
	}
	while( (n = getopt(argc, argv, "t:")) != EOF ){
		switch(n){
		case 't': max_try = atoi(optarg); break;
		default: usage(); break;
		}
	}
	if( argc - optind < 2 ) usage();


	sock = -1;
	memset(&dest_sin, 0, sizeof (dest_sin));

	host = argv[optind++];
	port = argv[optind++];

	if( (host_ent = gethostbyname( host )) ){
		dest_sin.sin_family = host_ent->h_addrtype;
		if( host_ent->h_length > sizeof( dest_sin.sin_addr ) ){
			fprintf(stderr,"%s: address length wrong\n", Prog);
			exit(1);
		}
		memcpy(&dest_sin.sin_addr, host_ent->h_addr_list[0], host_ent->h_length );
	} else 
		/* if( inet_pton( AF_INET, host, &dest_sin.sin_addr ) != 1 ){ */
		if( (dest_sin.sin_addr.s_addr = inet_addr( host )) == -1 ){
		fprintf(stderr,"%s: cannot find address for '%s'\n", Prog, host );
		exit(1);
	}
	n = atoi(port);
	if( n <= 0 ){
		fprintf(stderr,"%s: bad port '%s'\n", Prog, port );
		exit(1);
	}
	dest_sin.sin_port = htons(n);
    /* we get the printable from the socket address */
#if 0
    fprintf(stderr, "connect to '%s',port %d\n",
		inet_ntoa( dest_sin.sin_addr )),
		(int) ntohs(dest_sin.sin_port) );
#endif
	try = 0;
	do{ 
		if( sock != -1 ) close(sock );
		sock = -1;
		sock = socket(AF_INET, SOCK_STREAM, 0 );
		if( sock == -1 ){
			fprintf(stderr,"%s: socket() failed '%s'\n", Prog, strerror(errno) );
			exit(1);
		}
		n = connect(sock, (void *)&dest_sin, sizeof(dest_sin) );
		if( n == -1 && ++try < max_try ){
			sleep(1);
		} else {
			break;
		}
	}while( n == -1 );
	if( n == -1 ){
		fprintf(stderr, "%s: connect to '%s',port %d failed after %d tries - %s\n",
			Prog,
			inet_ntoa( dest_sin.sin_addr),
			(int) ntohs(dest_sin.sin_port), try, strerror(errno) );
		exit(1);
	}
	if( optind == argc ){
		do_send( sock, 0, "stdin" );
	} else for(; optind < argc; ++optind ){
		if( (n = open(argv[optind], O_RDONLY, 0)) == -1 ){
			fprintf(stderr, "%s: cannot open '%s' - %s\n",
				Prog, argv[optind], strerror(errno) );
			exit(1);
		}
		do_send( sock, n, argv[optind] );
		close(n);
	}
	/* we shut down the connection */
	shutdown(sock,1);
	while( (n = read(sock,&buffer,sizeof(buffer))) > 0 );
	close(sock);
	return(0);
}

void do_send( int sock, int fd, char *name )
{
	int cnt, n, i;
	while( (n = read(fd,buffer,sizeof(buffer))) > 0 ){
		for( cnt = i = 0; cnt >= 0 && i < n; i += cnt ){
			cnt = write(sock,buffer+i,n-i);
		}
		if( cnt < 0 ){
			fprintf(stderr, "%s: cannot write to remote host - %s\n",
				Prog, strerror(errno) );
			exit(1);
		}
	}
	if( n < 0 ){
		fprintf(stderr, "%s: cannot read from '%s' - %s\n",
			Prog, name, strerror(errno) );
		exit(1);
	}
}
