1 /* ============================================================================
2 * Copyright (C) 1998 Angus Mackay. All rights reserved;
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
10 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
11 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
13 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
14 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
15 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
16 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
17 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
19 * ============================================================================
20 */
21
22 /*
23 * $Id: tcpcat.c,v 1.24 2000/01/23 01:19:22 amackay Exp $
24 *
25 * tcpcat is a simple program that is like `cat' but it works over tcp streams
26 * to allow you to cat from one host to another.
27 *
28 * the host common way to use this program whould be something like this:
29 * on host a: $ tcpcat -l 63255 | gzip -dc | tar xvf -
30 * on host b: $ tcpcat -h hosta:63255 tcpcat-X.X.X.tar.gz
31 *
32 * this program has been tested under Linux 2.0 and Solaris 2.6.
33 *
34 */
35
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
39
40 #define HAVE_TERMIOS_H 1
41 #define HAVE_TCGETATTR 1
42 #define HAVE_TCSETATTR 1
43 #define HAVE_ON_EXIT 1
44
45 #ifdef HAVE_GETOPT_H
46 # include <getopt.h>
47 #endif
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #if HAVE_FCNTL_H
53 # include <fcntl.h>
54 #endif
55 #include <netinet/in.h>
56 #if HAVE_ARPA_INET_H
57 # include <arpa/inet.h>
58 #endif
59 #include <netdb.h>
60 #include <sys/socket.h>
61 #if HAVE_SYS_UN_H
62 # include <sys/un.h>
63 #endif
64 #if HAVE_SYS_TYPES_H
65 # include <sys/types.h>
66 #endif
67 #if HAVE_SIGNAL_H
68 # include <signal.h>
69 #endif
70
71 #if HAVE_SYS_TIME_H
72 # include <sys/time.h>
73 #endif
74
75 #ifdef HAVE_TERMIOS_H
76 # if !defined(HAVE_TCGETATTR) && !defined(HAVE_TCSETATTR)
77 # undef HAVE_TERMIOS_H
78 # endif
79 #endif
80
81 #ifdef HAVE_TERMIOS_H
82 # include <termios.h>
83 #else
84 # ifdef HAVE_TERMIO_H
85 # include <termio.h>
86 # else
87 # endif
88 #endif
89
90 #include "zlib.h"
91
92 #ifndef HAVE_HERROR
93 # define herror(x) fprintf(stderr, "%s: error\n", x)
94 #endif
95
96 #ifdef DEBUG
97 #define dprintf(x) if( options & OPT_DEBUG ) \
98 { \
99 fprintf(stderr, "%s,%d: ", __FILE__, __LINE__); \
100 fprintf x; \
101 }
102 #else
103 # define dprintf(x)
104 #endif
105
106 #define EXIT_NO_HOST 2
107
108 #define MIN_BUFFER_SIZE 1
109
110 /**************************************************/
111
112 static char *program_name;
113 static char *host = NULL;
114 static char *listen_port = NULL;
115 static char *connect_port = NULL;
116 static char *connect_bind_port = NULL;
117 static struct timeval *timeout = NULL;
118 static char *echo_file = NULL;
119
120 static volatile int server_sockfd;
121 static volatile int client_sockfd;
122 static volatile int client_sockfd2;
123 static volatile int echo_fd;
124 static FILE *echo_fp;
125
126 static int buffersize = 64*1024;
127 static int socketbuffersize = 0;
128
129 static uLong g_cksum = 0;
130
131 static int (*do_connect)(volatile int *sock, char *host, char *port);
132 static int (*do_listen)(volatile int *serv_sock, char *host, char *port);
133 static int (*do_accept)(volatile int *sock, volatile int serv_sock);
134
135 static int options;
136 static long bytes_copied;
137
138 #define OPT_DEBUG 0x0001
139 #define OPT_LISTEN 0x0002
140 #define OPT_QUIET 0x0004
141 #define OPT_INPUT 0x0008
142 #define OPT_OUTPUT 0x0010
143 #define OPT_VERBOSE 0x0020
144 #define OPT_CONNECT 0x0040
145 #define OPT_AF_UNIX 0x0080
146 #define OPT_CONTINUOUS 0x0100
147 #define OPT_NOBUF 0x0200
148 #define OPT_CKSUM 0x0400
149 #define OPT_ECHO 0x80000000 /* use sign bit for faster checking */
150
151 #define COPY_IN_OUT_QUIET 0
152 #define COPY_IN_OUT_VERB 1
153
154 /**************************************************/
155
156 void print_useage( void );
157 void print_version( void );
158 void parse_args( int argc, char **argv );
159 int do_connect_inet(volatile int *sock, char *host, char *port);
160 int do_connect_unix(volatile int *sock, char *host, char *port);
161 int do_listen_inet(volatile int *serv_sock, char *host, char *port);
162 int do_listen_unix(volatile int *serv_sock, char *host, char *port);
163 int do_accept_inet(volatile int *sock, volatile int serv_sock);
164 int do_accept_unix(volatile int *sock, volatile int serv_sock);
165 void copy_in_out_verb(int input_fd, int output_fd);
166 void copy_in_out_quiet(int input_fd, int output_fd);
167 void copy_in_out4_quiet(int input1_fd, int input2_fd, int output1_fd, int output2_fd);
168 #if defined(__BEOS__)
169 void copy_sin_fout_quiet(int input_fd, int output_fd);
170 void copy_sin_fout_verb(int input_fd, int output_fd);
171 void copy_fin_sout_quiet(int input_fd, int output_fd);
172 void copy_fin_sout_verb(int input_fd, int output_fd);
173 void copy_in_out4_not_available(int a, int b, int c, int d);
174 #endif
175 void set_input_buffer(int fd, int restore);
176 int main( int argc, char **argv );
177
178 /**************************************************/
179
xmalloc(size_t size)180 void *xmalloc(size_t size)
181 {
182 void *p;
183
184 p = malloc(size);
185 if(p == NULL)
186 {
187 fprintf(stderr, "out of memory\n");
188 exit(1);
189 }
190 return p;
191 }
192
print_useage(void)193 void print_useage( void )
194 {
195 fprintf(stdout, "useage: ");
196 fprintf(stdout, "%s [options] [file]...\n\n", program_name);
197 fprintf(stdout, " Options are:\n");
198 fprintf(stdout, " -B, --socket-buffer <n[kKmM]>\tuse n byte socket buffer\n");
199 fprintf(stdout, " -b, --buffer-size <n[kKmM]>\tuse n byte buffer\n");
200 fprintf(stdout, " -c, --continue\t\tcontinue to accept connections\n");
201 #ifdef DEBUG
202 fprintf(stdout, " -D, --debug\t\t\tturn on debuggin\n");
203 #endif
204 fprintf(stdout, " -e, --echo <file>\t\techo data to file\n");
205 fprintf(stdout, " -h, --host <host>[:<port>]\thost to connect to\n");
206 fprintf(stdout, " -i, --input\t\t\twhen listening input from stdin\n");
207 fprintf(stdout, " -l, --listen <port>\t\tlisten for connections on port\n");
208 fprintf(stdout, " -n, --nobuf\t\t\tif stdin is a terminal do not use line \n\t\t\t\t"
209 "buffering. generate a SIGQUIT (CTRL-\\) to stop \n\t\t\t\t"
210 "or use a timeout\n");
211 fprintf(stdout, " -o, --output\t\t\twhen connecting output to stdout\n");
212 fprintf(stdout, " -p, --port <port>\t\tuse port for connect or listen\n");
213 fprintf(stdout, " -P, --bind-port <port>\tuse port for binded connects (ipaddr:port works)\n");
214 fprintf(stdout, " -s, --sum\t\t\tprint Adler32 checksum\n");
215 fprintf(stdout, " -q, --quiet\t\t\tdon't print extra info\n");
216 fprintf(stdout, " -t, --timeout <period>\tused only when both -i and -o are specified\n");
217 fprintf(stdout, " -u, --unix-host <file>\taf_unix file to connect to\n");
218 fprintf(stdout, " -U, --unix-listen <file>\tlisten for connections on af_unix file\n");
219 fprintf(stdout, " -v, --verbose\t\t\tprint progress dots for stdin/out, "
220 "usually dots \n\t\t\t\tare only printed for sending files\n");
221 fprintf(stdout, " --help\t\t\tdisplay this help and exit\n");
222 fprintf(stdout, " --version\t\t\toutput version information and exit\n");
223 fprintf(stdout, " --credits\t\t\tprint the credits and exit\n");
224 fprintf(stdout, "\n");
225 fprintf(stdout, "using --input and --output basicly swap the roles of the\n");
226 fprintf(stdout, "client/server version of %s.\n", program_name);
227 fprintf(stdout, "\n");
228 }
229
print_version(void)230 void print_version( void )
231 {
232 fprintf(stdout, "%s: - %s - $Id: tcpcat.c,v 1.24 2000/01/23 01:19:22 amackay Exp $\n", program_name, VERSION);
233 }
234
print_credits(void)235 void print_credits( void )
236 {
237 fprintf( stdout, "AUTHORS / CONTRIBUTORS\n"
238 " Angus Mackay <amackay@gusnet.cx>\n"
239 "\n" );
240 }
241
242 #if HAVE_SIGNAL_H
sig_handler(int sig)243 RETSIGTYPE sig_handler(int sig)
244 {
245 char message[] = "interupted.\n";
246
247 write(2, message, sizeof(message)-1);
248
249 // clean up the terminal
250 if(options & OPT_NOBUF)
251 {
252 set_input_buffer(fileno(stdin), 1);
253 }
254
255 close(client_sockfd);
256 close(server_sockfd);
257 close(echo_fd);
258
259 // clean up the socket file
260 if( (options & OPT_AF_UNIX) && (options & OPT_LISTEN) && listen_port )
261 {
262 unlink(listen_port);
263 }
264 }
265 #endif
266
267 /*
268 * longfromstr
269 *
270 * a super atoi that takes things like
271 * 64k == 65536
272 * 0x10M == 16777216
273 * 013 == 11
274 * 43 == 43
275 *
276 */
longfromstr(char * str)277 long longfromstr(char *str)
278 {
279 int mult;
280 int lastchar;
281 long val;
282
283 lastchar = strlen(str);
284 lastchar = lastchar == 0 ? 0 : lastchar - 1;
285 switch(str[lastchar])
286 {
287 case 'k':
288 case 'K':
289 mult = 1024;
290 break;
291 case 'm':
292 case 'M':
293 mult = 1024*1024;
294 break;
295 case 'g':
296 case 'G':
297 mult = 1024*1024*1024;
298 break;
299 default:
300 mult = 1;
301 break;
302 }
303
304 val = strtol(str, NULL, 0) * mult;
305
306 return(val);
307 }
308
309 #ifdef HAVE_GETOPT_LONG
310 # define xgetopt( x1, x2, x3, x4, x5 ) getopt_long( x1, x2, x3, x4, x5 )
311 #else
312 # define xgetopt( x1, x2, x3, x4, x5 ) getopt( x1, x2, x3 )
313 #endif
314
parse_args(int argc,char ** argv)315 void parse_args( int argc, char **argv )
316 {
317 #ifdef HAVE_GETOPT_LONG
318 struct option long_options[] = {
319 {"socket-buffer", required_argument, 0, 'B'},
320 {"buffer-size", required_argument, 0, 'b'},
321 {"continue", no_argument, 0, 'c'},
322 {"debug", no_argument, 0, 'D'},
323 {"echo", required_argument, 0, 'e'},
324 {"host", required_argument, 0, 'h'},
325 {"input", no_argument, 0, 'i'},
326 {"listen", required_argument, 0, 'l'},
327 {"nobuf", no_argument, 0, 'n'},
328 {"output", no_argument, 0, 'o'},
329 {"port", required_argument, 0, 'p'},
330 {"bind-port", required_argument, 0, 'P'},
331 {"quiet", no_argument, 0, 'q'},
332 {"sum", no_argument, 0, 's'},
333 {"timeout", required_argument, 0, 't'},
334 {"unix-listen", required_argument, 0, 'U'},
335 {"unix-host", required_argument, 0, 'u'},
336 {"verbose", no_argument, 0, 'v'},
337 {"help", no_argument, 0, 'H'},
338 {"version", no_argument, 0, 'V'},
339 {"credits", no_argument, 0, 'C'},
340 {0,0,0,0}
341 };
342 #else
343 # define long_options NULL
344 #endif
345 int opt;
346 char *tmp;
347
348 while((opt = xgetopt(argc, argv, "B:b:cDe:h:il:noP:p:qst:U:u:vHVC", long_options,
349 NULL)) != -1)
350 {
351 switch (opt)
352 {
353 case 'B':
354 socketbuffersize = longfromstr(optarg);
355 if(socketbuffersize < MIN_BUFFER_SIZE)
356 {
357 fprintf(stderr, "invalid buffer size of %d, must be larger than %d byte%s\n",
358 socketbuffersize, MIN_BUFFER_SIZE, MIN_BUFFER_SIZE == 1 ? "" : "s");
359 exit(1);
360 }
361 dprintf((stderr, "socketbuffersize %d\n", socketbuffersize));
362 break;
363
364 case 'b':
365 buffersize = longfromstr(optarg);
366 if(buffersize < MIN_BUFFER_SIZE)
367 {
368 fprintf(stderr, "invalid buffer size of %d, must be larger than %d byte%s\n",
369 buffersize, MIN_BUFFER_SIZE, MIN_BUFFER_SIZE == 1 ? "" : "s");
370 exit(1);
371 }
372 dprintf((stderr, "buffersize %d\n", buffersize));
373 break;
374
375 case 'c':
376 options |= OPT_CONTINUOUS;
377 dprintf((stderr, "continuous enabled\n"));
378 break;
379
380 case 'D':
381 options |= OPT_DEBUG;
382 dprintf((stderr, "debugging on\n"));
383 break;
384
385 case 'e':
386 options |= OPT_ECHO;
387 options |= OPT_INPUT;
388 options |= OPT_OUTPUT;
389 if(echo_file)
390 {
391 free(echo_file);
392 }
393 echo_file = strdup(optarg);
394 dprintf((stderr, "echo_file: %s\n", echo_file));
395 break;
396
397 case 'h':
398 options |= OPT_CONNECT;
399 // look for the port and cut it off if found
400 tmp = strchr(optarg, ':');
401 if (tmp) {
402 *tmp++ = '\0';
403 if(connect_port)
404 {
405 free(connect_port);
406 }
407 connect_port = strdup(tmp);
408 }
409 if(host)
410 {
411 free(host);
412 }
413 host = strdup(optarg);
414 dprintf((stderr, "host: %s\n", host));
415 dprintf((stderr, "connect_port: %s\n", connect_port));
416 break;
417
418 case 'u':
419 options |= OPT_CONNECT;
420 options |= OPT_AF_UNIX;
421 if(connect_port)
422 {
423 free(connect_port);
424 }
425 connect_port = strdup(optarg);
426 dprintf((stderr, "connect_port: %s\n", connect_port));
427 break;
428
429 case 'H':
430 print_useage();
431 exit(0);
432 break;
433
434 case 'i':
435 options |= OPT_INPUT;
436 break;
437
438 case 'l':
439 options |= OPT_LISTEN;
440 if(listen_port)
441 {
442 free(listen_port);
443 }
444 listen_port = strdup(optarg);
445 dprintf((stderr, "listen_port: %s\n", listen_port));
446 break;
447
448 case 'n':
449 options |= OPT_NOBUF;
450 break;
451
452 case 'U':
453 options |= OPT_LISTEN;
454 options |= OPT_AF_UNIX;
455 if(listen_port)
456 {
457 free(listen_port);
458 }
459 listen_port = strdup(optarg);
460 dprintf((stderr, "listen_port: %s\n", listen_port));
461 break;
462
463 case 'o':
464 options |= OPT_OUTPUT;
465 break;
466
467 // only use the -p port if we don't already have ports
468 case 'p':
469 if(connect_port == NULL)
470 {
471 connect_port = strdup(optarg);
472 dprintf((stderr, "connect_port: %s\n", connect_port));
473 }
474 if(listen_port == NULL)
475 {
476 listen_port = strdup(optarg);
477 dprintf((stderr, "listen_port: %s\n", listen_port));
478 }
479 break;
480
481 case 'P':
482 if(connect_bind_port == NULL)
483 {
484 connect_bind_port = strdup(optarg);
485 dprintf((stderr, "connect_bind_port: %s\n", connect_bind_port));
486 }
487 break;
488
489 case 'q':
490 options |= OPT_QUIET;
491 dprintf((stderr, "options |= OPT_QUIET\n"));
492 break;
493
494 case 's':
495 options |= OPT_CKSUM;
496 dprintf((stderr, "options |= OPT_CKSUM\n"));
497 break;
498
499 case 't':
500 if(timeout)
501 {
502 free(timeout);
503 }
504 timeout = (struct timeval*)malloc((int)sizeof(struct timeval));
505 timeout->tv_sec = strtol(optarg, NULL, 10);
506 timeout->tv_usec = (atof(optarg) - timeout->tv_sec) * 1000000L;
507 dprintf((stderr, "timeout: %ld.%06ld\n", timeout->tv_sec, timeout->tv_usec));
508 break;
509
510 case 'v':
511 options |= OPT_VERBOSE;
512 break;
513
514 case 'V':
515 print_version();
516 exit(0);
517 break;
518
519 case 'C':
520 print_credits();
521 exit(0);
522 break;
523
524 default:
525 #ifdef HAVE_GETOPT_LONG
526 fprintf(stderr, "Try `%s --help' for more information\n", argv[0]);
527 #else
528 fprintf(stderr, "Try `%s -H' for more information\n", argv[0]);
529 fprintf(stderr, "warning: this program was compilied without getopt_long\n");
530 fprintf(stderr, " as such all long options will not work!\n");
531 #endif
532 exit(1);
533 break;
534 }
535 }
536
537 // we need a port
538 if( connect_port == NULL && listen_port == NULL )
539 {
540 #ifdef HAVE_GETOPT_LONG
541 fprintf(stderr, "Try `%s --help' for more information\n", argv[0]);
542 #else
543 fprintf(stderr, "Try `%s -H' for more information\n", argv[0]);
544 fprintf(stderr, "warning: this program was compilied without getopt_long\n");
545 fprintf(stderr, " as such all long options will not work!\n");
546 #endif
547 exit(1);
548 }
549 }
550
551 /*
552 * do_connect
553 *
554 * connect a socket and return the file descriptor
555 *
556 */
do_connect_common(volatile int * sock,char * host,char * port)557 int do_connect_common(volatile int *sock, char *host, char *port)
558 {
559 int oplen;
560 int sendsize;
561 int recvsize;
562
563 #if HAVE_SETSOCKOPT && defined(SO_SNDBUF) && defined(SO_RCVBUF)
564 if(socketbuffersize != 0)
565 {
566 sendsize = socketbuffersize;
567 oplen = sizeof(sendsize);
568 if(setsockopt(*sock, SOL_SOCKET, SO_SNDBUF,
569 (void *)&sendsize, oplen) == -1)
570 {
571 perror("setsockopt:SO_SNDBUF");
572 }
573 recvsize = socketbuffersize;
574 oplen = sizeof(recvsize);
575 if(setsockopt(*sock, SOL_SOCKET, SO_RCVBUF,
576 (void *)&recvsize, oplen) == -1)
577 {
578 perror("setsockopt:SO_RCVBUF");
579 }
580 }
581
582 if( options & OPT_VERBOSE )
583 {
584 oplen = sizeof(sendsize);
585 if(getsockopt(*sock, SOL_SOCKET, SO_SNDBUF,
586 (void *)&sendsize, &oplen) == -1)
587 {
588 perror("setsockopt:SO_SNDBUF");
589 }
590 oplen = sizeof(recvsize);
591 if(getsockopt(*sock, SOL_SOCKET, SO_RCVBUF,
592 (void *)&recvsize, &oplen) == -1)
593 {
594 perror("setsockopt:SO_RCVBUF");
595 }
596
597 fprintf(stderr, "using %d byte socket send buffer\n", sendsize);
598 fprintf(stderr, "using %d byte socket recv buffer\n", recvsize);
599 }
600 #endif
601
602 return 0;
603 }
604
605 /*
606 * do_connect
607 *
608 * connect a socket and return the file descriptor
609 *
610 */
do_connect_inet(volatile int * sock,char * host,char * port)611 int do_connect_inet(volatile int *sock, char *host, char *port)
612 {
613 struct sockaddr_in address;
614 struct hostent *hostinfo;
615 struct servent *servinfo;
616
617 // set up the socket
618 *sock = socket(AF_INET, SOCK_STREAM, 0);
619 address.sin_family = AF_INET;
620
621 // get the host address
622 hostinfo = gethostbyname(host);
623 if(!hostinfo)
624 {
625 herror("gethostbyname");
626 exit(EXIT_NO_HOST);
627 }
628 address.sin_addr = *(struct in_addr *)*hostinfo->h_addr_list;
629
630 // get the host port
631 servinfo = getservbyname(port, "tcp");
632 if(servinfo)
633 {
634 address.sin_port = servinfo->s_port;
635 }
636 else
637 {
638 address.sin_port = htons(atoi(port));
639 }
640
641 // bind the socket
642 if(connect_bind_port != NULL)
643 {
644 struct sockaddr_in bind_address;
645 struct servent *servinfo;
646 int len;
647 char* host;
648 char* port;
649 char* tmp;
650
651 bind_address.sin_family = AF_INET;
652
653 tmp = strchr(connect_bind_port, ':');
654 if(tmp)
655 {
656 *tmp++ = '\0';
657 port = tmp;
658 host = connect_bind_port;
659 }
660 else
661 {
662 host = NULL;
663 port = connect_bind_port;
664 }
665
666 if(host == NULL)
667 {
668 bind_address.sin_addr.s_addr = htonl(INADDR_ANY);
669 }
670 else
671 {
672 if(inet_aton(host, &(bind_address.sin_addr)) == 0)
673 {
674 fprintf(stderr, "can't decipher ipaddr: %s\n", host);
675 return(-1);
676 }
677 }
678
679 servinfo = getservbyname(port, "tcp");
680 if(servinfo)
681 {
682 bind_address.sin_port = servinfo->s_port;
683 }
684 else
685 {
686 bind_address.sin_port = htons(atoi(port));
687 }
688
689 len = sizeof(bind_address);
690 if( bind(*sock, (struct sockaddr *)&bind_address, len) != 0 )
691 {
692 perror("bind");
693 return(-1);
694 }
695 }
696
697 // connect the socket
698 if(connect(*sock, (struct sockaddr *)&address, sizeof(address)) != 0)
699 {
700 perror("connect");
701 return(-1);
702 }
703
704 // print out some info
705 if( !(options & OPT_QUIET) )
706 {
707 fprintf(stderr,
708 "connected to %s (%s) on port %d.\n",
709 host,
710 inet_ntoa(address.sin_addr),
711 ntohs(address.sin_port));
712 }
713 if( (options & OPT_ECHO) && echo_file != NULL )
714 {
715 fprintf(echo_fp,
716 "connected to %s (%s) on port %d.\n",
717 host,
718 inet_ntoa(address.sin_addr),
719 ntohs(address.sin_port));
720 }
721
722 return(do_connect_common(sock, host, port));
723 }
724
do_connect_unix(volatile int * sock,char * host,char * port)725 int do_connect_unix(volatile int *sock, char *host, char *port)
726 {
727 #if HAVE_SYS_UN_H
728 struct sockaddr_un address;
729
730 // set up the socket
731 *sock = socket(AF_UNIX, SOCK_STREAM, 0);
732 address.sun_family = AF_UNIX;
733 strcpy(address.sun_path, port);
734
735 // bind the socket
736 if(connect_bind_port != NULL)
737 {
738 struct sockaddr_un bind_address;
739 int len;
740
741 bind_address.sun_family = AF_UNIX;
742 strcpy(bind_address.sun_path, connect_bind_port);
743
744 // warning: you have to delete this socket file now
745 len = sizeof(bind_address);
746 if( bind(*sock, (struct sockaddr *)&bind_address, len) != 0 )
747 {
748 perror("bind");
749 return(-1);
750 }
751 }
752
753 // connect the socket
754 if(connect(*sock, (struct sockaddr *)&address, sizeof(address)) != 0)
755 {
756 perror("connect");
757 return(-1);
758 }
759
760 // print out some info
761 if( !(options & OPT_QUIET) )
762 {
763 fprintf(stderr, "connected to unix:%s.\n", port);
764 }
765 if( (options & OPT_ECHO) && echo_file != NULL )
766 {
767 fprintf(echo_fp, "connected to unix:%s.\n", port);
768 }
769
770
771 return(do_connect_common(sock, host, port));
772 #else
773 fprintf(stderr, "AF_UNIX support not enabled at compile time\n");
774 return(-1);
775 #endif
776 }
777
778 /*
779 * do_accept
780 *
781 * do_accept is a one shot deal so it simply sets up a server
782 * socket, accepts a single connection on that socket, copies
783 * all of the input data to stdout, then shuts down the server
784 * socket and the connected socket.
785 *
786 */
do_accept_common(volatile int * sock,volatile int serv_sock)787 int do_accept_common(volatile int *sock, volatile int serv_sock)
788 {
789 int oplen;
790 int sendsize;
791 int recvsize;
792
793 #if HAVE_SETSOCKOPT && defined(SO_SNDBUF) && defined(SO_RCVBUF)
794 if(socketbuffersize != 0)
795 {
796 sendsize = socketbuffersize;
797 oplen = sizeof(sendsize);
798 if(setsockopt(*sock, SOL_SOCKET, SO_SNDBUF,
799 (void *)&sendsize, oplen) == -1)
800 {
801 perror("setsockopt:SO_SNDBUF");
802 }
803 recvsize = socketbuffersize;
804 oplen = sizeof(recvsize);
805 if(setsockopt(*sock, SOL_SOCKET, SO_RCVBUF,
806 (void *)&recvsize, oplen) == -1)
807 {
808 perror("setsockopt:SO_RCVBUF");
809 }
810 }
811
812 if( options & OPT_VERBOSE )
813 {
814 oplen = sizeof(sendsize);
815 if(getsockopt(*sock, SOL_SOCKET, SO_SNDBUF,
816 (void *)&sendsize, &oplen) == -1)
817 {
818 perror("getsockopt:SO_SNDBUF");
819 }
820 oplen = sizeof(recvsize);
821 if(getsockopt(*sock, SOL_SOCKET, SO_RCVBUF,
822 (void *)&recvsize, &oplen) == -1)
823 {
824 perror("getsockopt:SO_RCVBUF");
825 }
826
827 fprintf(stderr, "using %d byte socket send buffer\n", sendsize);
828 fprintf(stderr, "using %d byte socket recv buffer\n", recvsize);
829 }
830 #endif
831
832 return 0;
833 }
834
do_listen_common(volatile int * serv_sock,char * host,char * port)835 int do_listen_common(volatile int *serv_sock, char *host, char *port)
836 {
837 return 0;
838 }
839
do_listen_unix(volatile int * serv_sock,char * host,char * port)840 int do_listen_unix(volatile int *serv_sock, char *host, char *port)
841 {
842 #ifdef HAVE_SYS_UN_H
843 int server_len;
844 int client_len;
845 struct sockaddr_un server_address;
846 struct sockaddr_un client_address;
847
848 // set up the server socket
849 if( (*serv_sock=socket(AF_UNIX, SOCK_STREAM, 0)) == -1 )
850 {
851 perror("socket");
852 return(-1);
853 }
854 server_address.sun_family = AF_UNIX;
855 strcpy(server_address.sun_path, port);
856
857 // bind it to a port
858 server_len = sizeof(server_address);
859 if( bind(*serv_sock, (struct sockaddr *)&server_address, server_len) != 0 )
860 {
861 perror("bind");
862 return(-1);
863 }
864
865 // listen with a backlog of one, this should be zero but the BeOS
866 // doesn't interpret 0 correctly and most OSes don't enforce a backlog
867 // of 0 anyway
868 if( listen(*serv_sock, 1) != 0 )
869 {
870 perror("listen");
871 return(-1);
872 }
873
874 // print out some info
875 if( !(options & OPT_QUIET) )
876 {
877 fprintf(stderr, "listening on unix:%s.\n", port);
878 }
879 if( (options & OPT_ECHO) && echo_file != NULL )
880 {
881 fprintf(echo_fp, "listening on unix:%s.\n", port);
882 }
883
884 return(do_listen_common(serv_sock, host, port));
885 #else
886 fprintf(stderr, "AF_UNIX support not enabled at compile time\n");
887 return(-1);
888 #endif
889 }
890
891 /*
892 * do_accept
893 *
894 * do_accept is a one shot deal so it simply sets up a server
895 * socket, accepts a single connection on that socket, copies
896 * all of the input data to stdout, then shuts down the server
897 * socket and the connected socket.
898 *
899 */
do_accept_unix(volatile int * sock,volatile int serv_sock)900 int do_accept_unix(volatile int *sock, volatile int serv_sock)
901 {
902 int server_len;
903 int client_len;
904 struct sockaddr_un server_address;
905 struct sockaddr_un client_address;
906
907 // accept a connection on the server socket
908 client_len = sizeof(client_address);
909 *sock = accept( serv_sock,
910 (struct sockaddr *)&client_address,
911 &client_len );
912
913 // check the socket
914 if( *sock == -1 )
915 {
916 perror("accept");
917 return(-1);
918 }
919
920 // print out some info
921 if( !(options & OPT_QUIET) )
922 {
923 fprintf(stderr, "connection from unix:%s.\n", client_address.sun_path);
924 }
925 if( (options & OPT_ECHO) && echo_file != NULL )
926 {
927 fprintf(echo_fp, "connection from unix:%s.\n", client_address.sun_path);
928 }
929
930 return(do_accept_common(sock, serv_sock));
931 }
932
do_listen_inet(volatile int * serv_sock,char * host,char * port)933 int do_listen_inet(volatile int *serv_sock, char *host, char *port)
934 {
935 int server_len;
936 int client_len;
937 struct sockaddr_in server_address;
938 struct sockaddr_in client_address;
939 int res;
940 int x;
941 #if HAVE_SETSOCKOPT
942 # ifdef SO_LINGER
943 struct linger ling;
944 # endif
945 #endif
946
947 // set up the server socket
948 if( (*serv_sock=socket(AF_INET, SOCK_STREAM, 0)) == -1 )
949 {
950 perror("socket");
951 return(-1);
952 }
953
954
955 #if HAVE_SETSOCKOPT
956 # ifdef SO_REUSEADDR
957 x = 1;
958 res = setsockopt(*serv_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&x, sizeof(x));
959 if(res == -1)
960 {
961 perror("setsockopt:SO_REUSEADDR");
962 }
963 # endif
964 # ifdef SO_LINGER
965 ling.l_onoff = 1;
966 ling.l_linger = 10000;
967 res = setsockopt(*serv_sock, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
968 if(res == -1)
969 {
970 perror("setsockopt:SO_LINGER");
971 }
972 # endif
973 #endif
974
975
976 server_address.sin_family = AF_INET;
977 server_address.sin_addr.s_addr = htonl(INADDR_ANY);
978 server_address.sin_port = htons(atoi(port));
979
980 // bind it to a port
981 server_len = sizeof(server_address);
982 if( bind(*serv_sock, (struct sockaddr *)&server_address, server_len) != 0 )
983 {
984 perror("bind");
985 return(-1);
986 }
987
988 // listen with a backlog of one, this should be zero but the BeOS
989 // doesn't interpret 0 correctly and most OSes don't enforce a backlog
990 // of 0 anyway
991 if( listen(*serv_sock, 1) != 0 )
992 {
993 perror("listen");
994 return(-1);
995 }
996
997 // print out some info
998 if( !(options & OPT_QUIET) )
999 {
1000 fprintf(stderr,
1001 "listening on %s port %d.\n",
1002 inet_ntoa(server_address.sin_addr),
1003 ntohs(server_address.sin_port) );
1004 }
1005
1006 return(do_listen_common(serv_sock, host, port));
1007 }
1008
do_accept_inet(volatile int * sock,volatile int serv_sock)1009 int do_accept_inet(volatile int *sock, volatile int serv_sock)
1010 {
1011 int server_len;
1012 int client_len;
1013 struct sockaddr_in server_address;
1014 struct sockaddr_in client_address;
1015 int res;
1016 int x;
1017 struct linger ling;
1018
1019 // accept a connection on the server socket
1020 client_len = sizeof(client_address);
1021 *sock = accept( serv_sock,
1022 (struct sockaddr *)&client_address,
1023 &client_len );
1024
1025 // check the socket
1026 if( *sock == -1 )
1027 {
1028 perror("accept");
1029 return(-1);
1030 }
1031
1032 // stop listening after we have 1 connection
1033 //close(serv_sock);
1034
1035 // print out some info
1036 if( !(options & OPT_QUIET) )
1037 {
1038 fprintf(stderr,
1039 "connection from %s on port %d.\n",
1040 inet_ntoa(client_address.sin_addr),
1041 ntohs(client_address.sin_port));
1042 }
1043 if( (options & OPT_ECHO) && echo_file != NULL )
1044 {
1045 fprintf(echo_fp,
1046 "connection from %s on port %d.\n",
1047 inet_ntoa(client_address.sin_addr),
1048 ntohs(client_address.sin_port));
1049 }
1050
1051 return(do_accept_common(sock, serv_sock));
1052 }
1053
read_data(int fd,void * buf,int bufsize)1054 int read_data(int fd, void* buf, int bufsize)
1055 {
1056 int bread = read(fd, buf, buffersize);
1057 if(options & OPT_CKSUM)
1058 {
1059 g_cksum = adler32(g_cksum, buf, bread);
1060 }
1061 return(bread);
1062 }
1063
revc_data(int fd,void * buf,int bufsize)1064 int revc_data(int fd, void* buf, int bufsize)
1065 {
1066 int bread = recv(fd, buf, buffersize, 0);
1067 if(options & OPT_CKSUM)
1068 {
1069 g_cksum = adler32(g_cksum, buf, bread);
1070 }
1071 return(bread);
1072 }
1073
1074 /*
1075 * copy_in_out_verb
1076 *
1077 * simply read the input file descriptor and write the
1078 * data to the output file descriptor.
1079 *
1080 * also ouput a progressmeter.
1081 *
1082 */
copy_in_out_verb(int input_fd,int output_fd)1083 void copy_in_out_verb(int input_fd, int output_fd)
1084 {
1085 char *buf;
1086 int bytes_read;
1087
1088 buf = xmalloc(buffersize);
1089
1090 while( (bytes_read=read_data(input_fd, buf, buffersize)) > 0 )
1091 {
1092 write(output_fd, buf, bytes_read);
1093 bytes_copied += bytes_read;
1094 fputc('.', stderr);
1095 }
1096
1097 free(buf);
1098 }
1099
1100 /*
1101 * copy_in_out_quiet
1102 *
1103 * simply read the input file descriptor and write the
1104 * data to the output file descriptor.
1105 *
1106 */
copy_in_out_quiet(int input_fd,int output_fd)1107 void copy_in_out_quiet(int input_fd, int output_fd)
1108 {
1109 char *buf;
1110 int bytes_read;
1111
1112 buf = xmalloc(buffersize);
1113
1114 while( (bytes_read=read_data(input_fd, buf, buffersize)) > 0 )
1115 {
1116 write(output_fd, buf, bytes_read);
1117 bytes_copied += bytes_read;
1118 }
1119
1120 free(buf);
1121 }
1122
1123 /*
1124 * copy_in_out4_quiet
1125 *
1126 * read input1_fd => write input2_fd
1127 * read input2_fd => write output_fd
1128 *
1129 * basicly just like telnet.
1130 *
1131 */
copy_in_out4_quiet(int input1_fd,int input2_fd,int output1_fd,int output2_fd)1132 void copy_in_out4_quiet(int input1_fd, int input2_fd, int output1_fd, int output2_fd)
1133 {
1134 char *buf;
1135 int bytes_read = 0;
1136 int max_fd;
1137 fd_set readfds;
1138 fd_set select_readfds;
1139 struct timeval *tv = NULL;
1140 int ret;
1141
1142 buf = xmalloc(buffersize);
1143
1144 FD_ZERO(&readfds);
1145 FD_SET(input1_fd, &readfds);
1146 FD_SET(input2_fd, &readfds);
1147
1148 max_fd = (input1_fd > input2_fd ? input1_fd : input2_fd);
1149 if(timeout != NULL)
1150 {
1151 tv = (struct timeval*)malloc(sizeof(struct timeval));
1152 if(tv == NULL)
1153 {
1154 fprintf(stderr, "internal error, timeout will be ignored\n");
1155 timeout = NULL;
1156 }
1157 }
1158
1159 for(;;)
1160 {
1161 // refresh our fd set and timeout
1162 memcpy(&select_readfds, &readfds, sizeof(readfds));
1163 if(timeout)
1164 {
1165 memcpy(tv, timeout, sizeof(struct timeval));
1166 }
1167
1168 // select on the readfds
1169 ret = select(max_fd + 1, &select_readfds, NULL, NULL, tv );
1170 dprintf((stderr, "select: %d\n", ret));
1171
1172 if ( ret == -1)
1173 {
1174 perror("select");
1175 break;
1176 }
1177 if( ret == 0 )
1178 {
1179 fprintf(stderr, "timeout\n");
1180 break;
1181 }
1182
1183 /* if we woke up on input1_fd do the data passing */
1184 if(FD_ISSET(input1_fd, &select_readfds))
1185 {
1186 if( (bytes_read=read_data(input1_fd, buf, buffersize) ) <= 0)
1187 break;
1188 if(write(output2_fd, buf, bytes_read) != bytes_read)
1189 break;
1190 if( options & OPT_ECHO )
1191 {
1192 write(echo_fd, "L: ", 3);
1193 write(echo_fd, buf, bytes_read);
1194 }
1195 dprintf((stderr, "transfered %d bytes (%d -> %d)\n", bytes_read,
1196 input1_fd, output2_fd));
1197 }
1198 else if(FD_ISSET(input2_fd, &select_readfds))
1199 {
1200 if( (bytes_read=read_data(input2_fd, buf, buffersize) ) <= 0)
1201 break;
1202 if(write(output1_fd, buf, bytes_read) != bytes_read)
1203 break;
1204 if( options & OPT_ECHO )
1205 {
1206 write(echo_fd, "H: ", 3);
1207 write(echo_fd, buf, bytes_read);
1208 }
1209 dprintf((stderr, "transfered %d bytes (%d -> %d)\n", bytes_read,
1210 input2_fd, output1_fd));
1211 }
1212 else
1213 {
1214 dprintf((stderr, "error: case not handled."));
1215 }
1216 bytes_copied += bytes_read;
1217 }
1218
1219 if(tv)
1220 {
1221 free(tv);
1222 }
1223
1224 free(buf);
1225 }
1226
1227 #if defined(__BEOS__)
1228 /*
1229 * needed for silly OSes
1230 */
copy_sin_fout_quiet(int input_fd,int output_fd)1231 void copy_sin_fout_quiet(int input_fd, int output_fd)
1232 {
1233 char *buf;
1234 int bytes_read;
1235
1236 buf = xmalloc(buffersize);
1237
1238 while( (bytes_read=recv_data(input_fd, buf, buffersize, 0)) > 0 )
1239 {
1240 write(output_fd, buf, bytes_read);
1241 bytes_copied += bytes_read;
1242 }
1243
1244 free(buf);
1245 }
copy_sin_fout_verb(int input_fd,int output_fd)1246 void copy_sin_fout_verb(int input_fd, int output_fd)
1247 {
1248 char *buf;
1249 int bytes_read;
1250
1251 buf = xmalloc(buffersize);
1252
1253 while( (bytes_read=recv_data(input_fd, buf, buffersize, 0)) > 0 )
1254 {
1255 write(output_fd, buf, bytes_read);
1256 bytes_copied += bytes_read;
1257 fputc('.', stderr);
1258 }
1259
1260 free(buf);
1261 }
copy_fin_sout_quiet(int input_fd,int output_fd)1262 void copy_fin_sout_quiet(int input_fd, int output_fd)
1263 {
1264 int bytes_read;
1265 char *buf;
1266
1267 buf = xmalloc(buffersize);
1268
1269 while( (bytes_read=read_data(input_fd, buf, buffersize)) > 0 )
1270 {
1271 send(output_fd, buf, bytes_read, 0);
1272 bytes_copied += bytes_read;
1273 }
1274
1275 free(buf);
1276 }
copy_fin_sout_verb(int input_fd,int output_fd)1277 void copy_fin_sout_verb(int input_fd, int output_fd)
1278 {
1279 char *buf;
1280 int bytes_read;
1281
1282 buf = xmalloc(buffersize);
1283
1284 while( (bytes_read=read_data(input_fd, buf, buffersize)) > 0 )
1285 {
1286 send(output_fd, buf, bytes_read, 0);
1287 bytes_copied += bytes_read;
1288 fputc('.', stderr);
1289 }
1290
1291 free(buf);
1292 }
copy_in_out4_not_available(int a,int b,int c,int d)1293 void copy_in_out4_not_available(int a, int b, int c, int d)
1294 {
1295 fprintf( stderr,
1296 "this functionality is not abailable due to the fact that the OS\n"
1297 "that you are using spererates socket descriptors from file descriptorss.\n"
1298 "the feature could be implemented by using two threads but that isn't very\n"
1299 "pretty.\n" );
1300 }
1301 #endif
1302
1303 /*
1304 * enable or restore terminal line buffering state
1305 */
set_input_buffer(int fd,int restore)1306 void set_input_buffer(int fd, int restore)
1307 {
1308 #ifdef HAVE_TERMIOS_H
1309 static struct termios orig;
1310 struct termios new;
1311 #else
1312 # ifdef HAVE_TERMIO_H
1313 static struct termio orig;
1314 struct termio new;
1315 # endif
1316 #endif
1317 static int need_restore = 0;
1318
1319
1320 if(!isatty(fd))
1321 {
1322 return;
1323 }
1324
1325 dprintf((stderr, "restore: %d\n", restore));
1326 if(!restore)
1327 {
1328 #ifdef HAVE_TERMIOS_H
1329 if(!need_restore)
1330 {
1331 if(tcgetattr(fd, &orig) != 0)
1332 {
1333 perror("tcgetattr");
1334 }
1335 }
1336 new = orig;
1337
1338 dprintf((stderr, "iflag: 0x%08x oflag: 0x%08x cflag: 0x%08x lflag: 0x%08x\n",
1339 new.c_iflag, new.c_oflag, new.c_cflag, new.c_lflag));
1340
1341 new.c_lflag &= ~ICANON;
1342
1343 dprintf((stderr, "iflag: 0x%08x oflag: 0x%08x cflag: 0x%08x lflag: 0x%08x\n",
1344 new.c_iflag, new.c_oflag, new.c_cflag, new.c_lflag));
1345
1346 if(tcsetattr(fd, TCSANOW, &new) != 0)
1347 {
1348 perror("tcsetattr");
1349 }
1350 else
1351 {
1352 need_restore = 1;
1353 }
1354 #else
1355 # ifdef HAVE_TERMIO_H
1356 if(!need_restore)
1357 {
1358 if(ioctl(fd, TCGETA, &orig) != 0)
1359 {
1360 perror("ioctl");
1361 }
1362 }
1363 new = orig;
1364
1365 dprintf((stderr, "iflag: 0x%08x oflag: 0x%08x cflag: 0x%08x lflag: 0x%08x\n",
1366 new.c_iflag, new.c_oflag, new.c_cflag, new.c_lflag));
1367
1368 new.c_lflag &= ~ICANON;
1369
1370 dprintf((stderr, "iflag: 0x%08x oflag: 0x%08x cflag: 0x%08x lflag: 0x%08x\n",
1371 new.c_iflag, new.c_oflag, new.c_cflag, new.c_lflag));
1372
1373 if(ioctl(fd, TCSETA, &new) != 0)
1374 {
1375 perror("ioctl");
1376 }
1377 else
1378 {
1379 need_restore = 1;
1380 }
1381 # else
1382 # endif
1383 #endif
1384 }
1385 else
1386 {
1387 if(!need_restore)
1388 {
1389 return;
1390 }
1391 #ifdef HAVE_TERMIOS_H
1392 if(tcsetattr(fd, TCSANOW, &orig) != 0)
1393 {
1394 perror("tcgetattr");
1395 }
1396 else
1397 {
1398 need_restore = 0;
1399 }
1400 #else
1401 # ifdef HAVE_TERMIO_H
1402 if(ioctl(fd, TCSETA, &orig) != 0)
1403 {
1404 perror("ioctl");
1405 }
1406 else
1407 {
1408 need_restore = 0;
1409 }
1410 # else
1411 # endif
1412 #endif
1413 }
1414
1415 }
1416
print_sum(void)1417 void print_sum(void)
1418 {
1419 fprintf(stderr, "checksum: %u\n", g_cksum);
1420 }
1421
main(int argc,char ** argv)1422 int main( int argc, char **argv )
1423 {
1424 int i;
1425 int input_fd;
1426 struct timeval time1;
1427 struct timeval time2;
1428 int first_arg;
1429 void (*copy_in_out4_fp)(int, int, int, int);
1430 void (*copy_sin_fout_fp)(int, int);
1431 void (*copy_fin_sout_fp)(int, int);
1432 void (*send_file_fp)(int, int);
1433
1434 dprintf((stderr, "staring...\n"));
1435
1436 program_name = argv[0];
1437 options = 0;
1438 bytes_copied = 0;
1439 timeout = NULL;
1440
1441 #if HAVE_SIGNAL_H
1442 // catch user interupts
1443 signal(SIGINT, sig_handler);
1444 signal(SIGQUIT, sig_handler);
1445 #endif
1446
1447 parse_args(argc, argv);
1448 first_arg = optind;
1449
1450 // set defaults
1451 if( !host )
1452 {
1453 host = strdup("localhost");
1454 }
1455
1456 // set socket domain
1457 if((options & OPT_AF_UNIX))
1458 {
1459 do_connect = do_connect_unix;
1460 do_listen = do_listen_unix;
1461 do_accept = do_accept_unix;
1462 }
1463 else
1464 {
1465 do_connect = do_connect_inet;
1466 do_listen = do_listen_inet;
1467 do_accept = do_accept_inet;
1468 }
1469
1470 // corelate options
1471 if( (options & OPT_CONNECT) && (options & OPT_LISTEN) )
1472 {
1473 options |= OPT_INPUT;
1474 options |= OPT_OUTPUT;
1475 }
1476
1477 // more error checking
1478 if( !(options & OPT_CONNECT) && connect_bind_port != NULL)
1479 {
1480 fprintf(stderr, "you can not use --bind-port if you are not connecting, \njust use --port instead\n");
1481 exit(1);
1482 }
1483
1484 // if we are listening and not doing input we do output by default
1485 if( (options & OPT_LISTEN) && !(options & OPT_INPUT) )
1486 {
1487 options |= OPT_OUTPUT;
1488 }
1489 // if we are connecting and not doing output we do input by default
1490 if( !(options & OPT_LISTEN) && !(options & OPT_OUTPUT) )
1491 {
1492 options |= OPT_INPUT;
1493 }
1494
1495 dprintf((stderr, "options: 0x%04X\n", options));
1496 dprintf((stderr, "host: %s\n", host ? host : "(null)"));
1497 dprintf((stderr, "connect_port: %s\n", connect_port ? connect_port : "(null)"));
1498 dprintf((stderr, "listen_port: %s\n", listen_port ? listen_port : "(null)"));
1499
1500 // check for conflicting options
1501 if( (first_arg != argc) && (options & OPT_OUTPUT) )
1502 {
1503 fprintf(stderr, "Error: when using the output (`-o') option files can");
1504 fprintf(stderr, " not be supplied\n");
1505 exit(1);
1506 }
1507
1508 /*
1509 * set up the function pointers to handle for silly OSes and
1510 * the options
1511 */
1512 if( (options & OPT_VERBOSE) && !(options & OPT_QUIET) )
1513 {
1514 #if __BEOS__
1515 copy_in_out4_fp = copy_in_out4_not_available;
1516 copy_fin_sout_fp = copy_fin_sout_verb;
1517 copy_sin_fout_fp = copy_sin_fout_verb;
1518 send_file_fp = copy_fin_sout_verb;
1519 #else
1520 copy_in_out4_fp = copy_in_out4_quiet;
1521 copy_fin_sout_fp = copy_in_out_verb;
1522 copy_sin_fout_fp = copy_in_out_verb;
1523 send_file_fp = copy_in_out_verb;
1524 #endif
1525 }
1526 else
1527 {
1528 #if __BEOS__
1529 copy_in_out4_fp = copy_in_out4_not_available;
1530 copy_fin_sout_fp = copy_fin_sout_quiet;
1531 copy_sin_fout_fp = copy_sin_fout_quiet;
1532 if( options & OPT_QUIET)
1533 {
1534 send_file_fp = copy_fin_sout_quiet;
1535 }
1536 else
1537 {
1538 send_file_fp = copy_fin_sout_verb;
1539 }
1540 #else
1541 copy_in_out4_fp = copy_in_out4_quiet;
1542 copy_fin_sout_fp = copy_in_out_quiet;
1543 copy_sin_fout_fp = copy_in_out_quiet;
1544 if( options & OPT_QUIET)
1545 {
1546 send_file_fp = copy_in_out_quiet;
1547 }
1548 else
1549 {
1550 send_file_fp = copy_in_out_verb;
1551 }
1552 #endif
1553 }
1554
1555 if( options & OPT_VERBOSE )
1556 {
1557 fprintf(stderr, "using %d byte buffer\n", buffersize);
1558 }
1559
1560 // open our echo file
1561 if( (options & OPT_ECHO) && echo_file != NULL )
1562 {
1563 if( (echo_fd=open(echo_file, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1 )
1564 {
1565 perror(echo_file);
1566 exit(1);
1567 }
1568 if( (echo_fp=fdopen(echo_fd, "w")) == NULL)
1569 {
1570 perror(echo_file);
1571 exit(1);
1572 }
1573 // no buffering on the echo file so we can mix calls to write
1574 // and fprintf
1575 setvbuf(echo_fp, NULL, _IONBF, 0);
1576 }
1577
1578 if(options & OPT_NOBUF)
1579 {
1580 set_input_buffer(fileno(stdin), 0);
1581 }
1582
1583 server_sockfd = -1;
1584 do
1585 {
1586 if( (options & OPT_ECHO) && echo_file != NULL )
1587 {
1588 fprintf(echo_fp, "=============\n");
1589 }
1590
1591 // open up our sockets
1592 if( (options & OPT_LISTEN) && (options & OPT_CONNECT) )
1593 {
1594 if( server_sockfd == -1 )
1595 {
1596 if( do_listen(&server_sockfd, NULL, listen_port) != 0 )
1597 {
1598 fprintf(stderr, "error creating server socket\n");
1599 exit(1);
1600 }
1601 }
1602 if( do_accept(&client_sockfd, server_sockfd) != 0 )
1603 {
1604 fprintf(stderr, "error accepting connections\n");
1605 exit(1);
1606 }
1607 if(!(options & OPT_CONTINUOUS))
1608 {
1609 // stop listening after we have 1 connection
1610 close(server_sockfd);
1611 }
1612 if( do_connect(&client_sockfd2, host, connect_port) != 0 )
1613 {
1614 fprintf(stderr, "error connecting socket\n");
1615 exit(1);
1616 }
1617 }
1618 else if( options & OPT_LISTEN )
1619 {
1620 if( server_sockfd == -1 )
1621 {
1622 if( do_listen(&server_sockfd, NULL, listen_port) != 0 )
1623 {
1624 fprintf(stderr, "error creating server socket\n");
1625 exit(1);
1626 }
1627 }
1628 if( do_accept(&client_sockfd, server_sockfd) != 0 )
1629 {
1630 fprintf(stderr, "error accepting connections\n");
1631 exit(1);
1632 }
1633 if(!(options & OPT_CONTINUOUS))
1634 {
1635 // stop listening after we have 1 connection
1636 close(server_sockfd);
1637 }
1638 }
1639 else if( options & OPT_CONNECT )
1640 {
1641 if( do_connect(&client_sockfd, host, connect_port) != 0 )
1642 {
1643 fprintf(stderr, "error connecting socket\n");
1644 exit(1);
1645 }
1646 }
1647
1648 gettimeofday(&time1, NULL);
1649
1650 // if we don't have files supplied on the command line
1651 if( first_arg == argc )
1652 {
1653 /*
1654 * figure out what to do,
1655 * if we have -i and -o then act like
1656 * telnet, otherwise check for -o or -l if not found default
1657 * to read in, write out.
1658 */
1659 if( (options & OPT_OUTPUT) && (options & OPT_INPUT) )
1660 {
1661 if( (options & OPT_CONNECT) && (options & OPT_LISTEN) )
1662 {
1663 copy_in_out4_fp(client_sockfd, client_sockfd2, client_sockfd, client_sockfd2);
1664 }
1665 else
1666 {
1667 // read socket, stdin, write stdout
1668 copy_in_out4_fp(STDIN_FILENO, client_sockfd, STDOUT_FILENO, client_sockfd);
1669 }
1670 }
1671 else if( (options & OPT_OUTPUT) )
1672 {
1673 if(options & OPT_VERBOSE)
1674 {
1675 fprintf(stderr, "receiving ");
1676 }
1677 // read socket, write stdout
1678 copy_sin_fout_fp(client_sockfd, STDOUT_FILENO);;
1679 if(options & OPT_VERBOSE)
1680 {
1681 fprintf(stderr, " done.\n");
1682 }
1683 }
1684 else if( (options & OPT_INPUT) )
1685 {
1686 if(options & OPT_VERBOSE)
1687 {
1688 fprintf(stderr, "sending ");
1689 }
1690 // read stdin, write socket
1691 copy_fin_sout_fp(STDIN_FILENO, client_sockfd);
1692 if(options & OPT_VERBOSE)
1693 {
1694 fprintf(stderr, " done.\n");
1695 }
1696 }
1697 else
1698 {
1699 dprintf((stderr, "case not handeled\n"));
1700 }
1701 }
1702 else
1703 {
1704 // proccess the files
1705 for(i=first_arg; i<argc; i++)
1706 {
1707 dprintf((stderr, "processing file %s...\n", argv[i]));
1708 if( (input_fd=open(argv[i], O_RDONLY)) == -1 )
1709 {
1710 perror(argv[i]);
1711 continue;
1712 }
1713 if( !(options & OPT_QUIET) )
1714 {
1715 fprintf(stderr, "sending file %s ", argv[i]);
1716 }
1717
1718 // read file, write socket
1719 send_file_fp(input_fd, client_sockfd);
1720
1721 if( !(options & OPT_QUIET) )
1722 {
1723 fprintf(stderr, " done.\n");
1724 }
1725
1726 if(close(input_fd) != 0)
1727 {
1728 perror(argv[i]);
1729 }
1730 }
1731 }
1732
1733 gettimeofday(&time2, NULL);
1734
1735 close(client_sockfd);
1736 if( (options & OPT_LISTEN) && (options & OPT_CONNECT) )
1737 {
1738 close(client_sockfd2);
1739 }
1740
1741 if( !(options & OPT_QUIET) )
1742 {
1743 double took;
1744
1745 took = ((double)time2.tv_sec - (double)time1.tv_sec +
1746 (double)time2.tv_usec/1000000L -
1747 (double)time1.tv_usec/1000000L);
1748
1749 if( (options & OPT_OUTPUT) && (options & OPT_INPUT) )
1750 {
1751 fprintf( stderr,
1752 "%li bytes transfered in %.2f seconds (%.2f K/s)\n",
1753 bytes_copied,
1754 took,
1755 bytes_copied/took/1024 );
1756 }
1757 else if( (options & OPT_OUTPUT) )
1758 {
1759 fprintf( stderr,
1760 "%li bytes written to stdout in %.2f seconds (%.2f K/s)\n",
1761 bytes_copied,
1762 took,
1763 bytes_copied/took/1024 );
1764 }
1765 else if( (options & OPT_INPUT) )
1766 {
1767 fprintf( stderr,
1768 "%li bytes written to %s:%s in %.2f seconds (%.2f K/s)\n",
1769 bytes_copied,
1770 host,
1771 connect_port,
1772 took,
1773 bytes_copied/took/1024 );
1774 }
1775 }
1776 }
1777 while(options & OPT_CONTINUOUS);
1778
1779 if( (options & OPT_ECHO) && echo_file != NULL )
1780 {
1781 fclose(echo_fp);
1782 close(echo_fd);
1783 }
1784
1785 if(options & OPT_NOBUF)
1786 {
1787 set_input_buffer(fileno(stdin), 1);
1788 }
1789
1790 // clean up the socket file
1791 if( (options & OPT_AF_UNIX) && (options & OPT_LISTEN) && listen_port )
1792 {
1793 unlink(listen_port);
1794 }
1795
1796 if(options & OPT_CKSUM)
1797 {
1798 print_sum();
1799 }
1800
1801 dprintf((stderr, "done\n"));
1802 return 0;
1803 }
1804
1805