/*
* 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);
       }
}