X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/332cf6df7c32dbaa47cbfe515121da7bd53974e8..5dd14f0c3388f69932d521915e039e32b9e6d970:/socket.c diff --git a/socket.c b/socket.c index 823452f3..87b1ec34 100644 --- a/socket.c +++ b/socket.c @@ -3,11 +3,12 @@ * * 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 version 2 as - * published by the Free Software Foundation. + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,8 +16,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + * with this program; if not, visit the http://fsf.org website. */ /* This file is now converted to use the new-style getaddrinfo() @@ -25,12 +25,15 @@ * emulate it using the KAME implementation. */ #include "rsync.h" +#include "itypes.h" #include #include #include extern char *bind_address; +extern char *sockopts; extern int default_af_hint; +extern int connect_timeout; #ifdef HAVE_SIGACTION static struct sigaction sigact; @@ -156,6 +159,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 . @@ -224,7 +232,7 @@ int open_socket_out(char *host, int port, const char *bind_addr, } *cp++ = '\0'; strlcpy(portbuf, cp, sizeof portbuf); - if (verbose >= 2) { + if (DEBUG_GTE(CONNECT, 1)) { rprintf(FINFO, "connection via http proxy %s port %s\n", h, portbuf); } @@ -260,11 +268,28 @@ 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); + } + + set_socket_options(s, sockopts); + 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,7 +325,43 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr, { char *prog = getenv("RSYNC_CONNECT_PROG"); - if (verbose >= 2) { + 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 (DEBUG_GTE(CONNECT, 1)) { rprintf(FINFO, "%sopening tcp connection to %s port %d\n", prog ? "Using RSYNC_CONNECT_PROG instead of " : "", host, port); @@ -374,6 +435,10 @@ static int *open_socket_in(int type, int port, const char *bind_addr, setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof one); + if (sockopts) + set_socket_options(s, sockopts); + else + set_socket_options(s, lp_socket_options()); #ifdef IPV6_V6ONLY if (resp->ai_family == AF_INET6) { @@ -408,7 +473,7 @@ static int *open_socket_in(int type, int port, const char *bind_addr, /* Only output the socket()/bind() messages if we were totally * unsuccessful, or if the daemon is being run with -vv. */ for (s = 0; s < ecnt; s++) { - if (!i || verbose > 1) + if (!i || DEBUG_GTE(BIND, 1)) rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]), 0); free(errmsgs[s]); } @@ -666,35 +731,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 @@ -793,7 +829,7 @@ int sock_exec(const char *prog) rsyserr(FERROR, errno, "socketpair_tcp failed"); return -1; } - if (verbose >= 2) + if (DEBUG_GTE(CMD, 1)) rprintf(FINFO, "Running socket program: \"%s\"\n", prog); if (fork() == 0) { close(fd[0]);