1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17/*
18 * tcpsend [-t timeout] host port [files]
19 *
20 * open a TCP/IP connection to port on host and send files
21 *  Super lightweight LPR ???
22 * tcpsend.c,v 1.1 2000/10/14 21:11:23 papowell Exp
23 */
24
25#include <unistd.h>
26#include <stdlib.h>
27#include <sys/types.h>
28#include <fcntl.h>
29#include <sys/socket.h>
30#include <stdio.h>
31#include <netinet/in.h>
32#include <netdb.h>
33#include <arpa/inet.h>
34#include <errno.h>
35#include <string.h>
36#include <signal.h>
37
38char *Prog = "???";
39
40char *msg[] = {
41	"use: %s [-t timeout] host port [files]",
42	"  -t timeout  - try connecting for timeout seconds",
43	0
44};
45
46int max_try = 10;
47
48void do_send( int sock, int fd, char *name );
49void Set_linger( int sock, int n );
50
51void usage(void)
52{
53	int i;
54	fprintf( stderr, msg[0], Prog );
55	fprintf( stderr, "\n");
56	for( i = 1; msg[i]; ++i ){
57		fprintf( stderr, "%s\n", msg[i] );
58	}
59	exit(1);
60}
61
62char buffer[10*1024];
63
64int main( int argc, char **argv )
65{
66	int n, try;
67	int sock;	         /* socket */
68	char *s, *host, *port;
69	struct sockaddr_in dest_sin;     /* inet socket address */
70	struct hostent *host_ent = 0;
71
72	(void)signal( SIGPIPE, SIG_IGN );
73	if( argv[0] ) Prog = argv[0];
74	if( (s = strrchr(Prog,'/')) ){
75		Prog = s+1;
76	}
77	while( (n = getopt(argc, argv, "t:")) != EOF ){
78		switch(n){
79		case 't': max_try = atoi(optarg); break;
80		default: usage(); break;
81		}
82	}
83	if( argc - optind < 2 ) usage();
84
85
86	sock = -1;
87	memset(&dest_sin, 0, sizeof (dest_sin));
88
89	host = argv[optind++];
90	port = argv[optind++];
91
92	if( (host_ent = gethostbyname( host )) ){
93		dest_sin.sin_family = host_ent->h_addrtype;
94		if( host_ent->h_length > sizeof( dest_sin.sin_addr ) ){
95			fprintf(stderr,"%s: address length wrong\n", Prog);
96			exit(1);
97		}
98		memcpy(&dest_sin.sin_addr, host_ent->h_addr_list[0], host_ent->h_length );
99	} else
100		/* if( inet_pton( AF_INET, host, &dest_sin.sin_addr ) != 1 ){ */
101		if( (dest_sin.sin_addr.s_addr = inet_addr( host )) == -1 ){
102		fprintf(stderr,"%s: cannot find address for '%s'\n", Prog, host );
103		exit(1);
104	}
105	n = atoi(port);
106	if( n <= 0 ){
107		fprintf(stderr,"%s: bad port '%s'\n", Prog, port );
108		exit(1);
109	}
110	dest_sin.sin_port = htons(n);
111    /* we get the printable from the socket address */
112#if 0
113    fprintf(stderr, "connect to '%s',port %d\n",
114		inet_ntoa( dest_sin.sin_addr )),
115		(int) ntohs(dest_sin.sin_port) );
116#endif
117	try = 0;
118	do{
119		if( sock != -1 ) close(sock );
120		sock = -1;
121		sock = socket(AF_INET, SOCK_STREAM, 0 );
122#ifdef WINDOW_1
123int windowsize=1024;
124setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&windowsize, sizeof(windowsize));
125aaaaaa=fopen("/tmp/qqqqq", "a");
126fprintf(aaaaaa, "tcp_send: main\n");
127fclose(aaaaaa);
128#endif
129		if( sock == -1 ){
130			fprintf(stderr,"%s: socket() failed '%s'\n", Prog, strerror(errno) );
131			exit(1);
132		}
133		n = connect(sock, (void *)&dest_sin, sizeof(dest_sin) );
134		if( n == -1 && ++try < max_try ){
135			sleep(1);
136		} else {
137			break;
138		}
139	}while( n == -1 );
140	if( n == -1 ){
141		fprintf(stderr, "%s: connect to '%s',port %d failed after %d tries - %s\n",
142			Prog,
143			inet_ntoa( dest_sin.sin_addr),
144			(int) ntohs(dest_sin.sin_port), try, strerror(errno) );
145		exit(1);
146	}
147	if( optind == argc ){
148		do_send( sock, 0, "stdin" );
149	} else for(; optind < argc; ++optind ){
150		if( (n = open(argv[optind], O_RDONLY, 0)) == -1 ){
151			fprintf(stderr, "%s: cannot open '%s' - %s\n",
152				Prog, argv[optind], strerror(errno) );
153			exit(1);
154		}
155		do_send( sock, n, argv[optind] );
156		close(n);
157	}
158	/* we shut down the connection */
159	shutdown(sock,1);
160	while( (n = read(sock,&buffer,sizeof(buffer))) > 0 );
161	close(sock);
162	return(0);
163}
164
165void do_send( int sock, int fd, char *name )
166{
167	int cnt, n, i;
168	while( (n = read(fd,buffer,sizeof(buffer))) > 0 ){
169		for( cnt = i = 0; cnt >= 0 && i < n; i += cnt ){
170			cnt = write(sock,buffer+i,n-i);
171		}
172		if( cnt < 0 ){
173			fprintf(stderr, "%s: cannot write to remote host - %s\n",
174				Prog, strerror(errno) );
175			exit(1);
176		}
177	}
178	if( n < 0 ){
179		fprintf(stderr, "%s: cannot read from '%s' - %s\n",
180			Prog, name, strerror(errno) );
181		exit(1);
182	}
183}
184