X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/8e41b68e8f975c02a5d9281be780ba5d1a385107..99c3e591b201c28b8fe22c881332f8a4888e69b8:/socket.c diff --git a/socket.c b/socket.c index f0b1318a..65ee61aa 100644 --- a/socket.c +++ b/socket.c @@ -3,7 +3,7 @@ * * Copyright (C) 1992-2001 Andrew Tridgell * Copyright (C) 2001, 2002 Martin Pool - * Copyright (C) 2003-2007 Wayne Davison + * Copyright (C) 2003-2008 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,12 +25,14 @@ * emulate it using the KAME implementation. */ #include "rsync.h" +#include "ifuncs.h" #include #include #include extern char *bind_address; extern int default_af_hint; +extern int connect_timeout; #ifdef HAVE_SIGACTION static struct sigaction sigact; @@ -156,6 +158,11 @@ int try_bind_local(int s, int ai_family, int ai_socktype, return -1; } +/* connect() timeout handler based on alarm() */ +static RETSIGTYPE contimeout_handler(UNUSED(int val)) +{ + connect_timeout = -1; +} /** * Open a socket to a tcp remote host with the specified port . @@ -260,11 +267,27 @@ int open_socket_out(char *host, int port, const char *bind_addr, s = -1; continue; } - if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { + if (connect_timeout > 0) { + SIGACTION(SIGALRM, contimeout_handler); + alarm(connect_timeout); + } + + while (connect(s, res->ai_addr, res->ai_addrlen) < 0) { + if (connect_timeout < 0) + exit_cleanup(RERR_CONTIMEOUT); + if (errno == EINTR) + continue; close(s); s = -1; - continue; + break; } + + if (connect_timeout > 0) + alarm(0); + + if (s < 0) + continue; + if (proxied && establish_proxy_connection(s, host, port, proxy_user, proxy_pass) != 0) { @@ -300,6 +323,42 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr, { char *prog = getenv("RSYNC_CONNECT_PROG"); + if (prog && strchr(prog, '%')) { + int hlen = strlen(host); + int len = strlen(prog) + 1; + char *f, *t; + for (f = prog; *f; f++) { + if (*f != '%') + continue; + /* Compute more than enough room. */ + if (f[1] == '%') + f++; + else + len += hlen; + } + f = prog; + if (!(prog = new_array(char, len))) + out_of_memory("open_socket_out_wrapped"); + for (t = prog; *f; f++) { + if (*f == '%') { + switch (*++f) { + case '%': + /* Just skips the extra '%'. */ + break; + case 'H': + memcpy(t, host, hlen); + t += hlen; + continue; + default: + f--; /* pass % through */ + break; + } + } + *t++ = *f; + } + *t = '\0'; + } + if (verbose >= 2) { rprintf(FINFO, "%sopening tcp connection to %s port %d\n", prog ? "Using RSYNC_CONNECT_PROG instead of " : "", @@ -666,35 +725,6 @@ void set_socket_options(int fd, char *options) free(options); } -/** - * Become a daemon, discarding the controlling terminal - **/ -void become_daemon(void) -{ - int i; - - if (fork()) { - _exit(0); - } - - /* detach from the terminal */ -#ifdef HAVE_SETSID - setsid(); -#elif defined TIOCNOTTY - i = open("/dev/tty", O_RDWR); - if (i >= 0) { - ioctl(i, (int)TIOCNOTTY, (char *)0); - close(i); - } -#endif - /* make sure that stdin, stdout an stderr don't stuff things - * up (library functions, for example) */ - for (i = 0; i < 3; i++) { - close(i); - open("/dev/null", O_RDWR); - } -} - /** * This is like socketpair but uses tcp. It is used by the Samba