|
version 1.1, 2012/02/17 15:09:30
|
version 1.1.1.4, 2021/03/17 00:32:36
|
|
Line 3
|
Line 3
|
| * |
* |
| * Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org> |
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org> |
| * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org> |
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org> |
| * Copyright (C) 2003-2009 Wayne Davison | * Copyright (C) 2003-2020 Wayne Davison |
| * |
* |
| * This program is free software; you can redistribute it and/or modify |
* 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 |
* it under the terms of the GNU General Public License as published by |
|
Line 25
|
Line 25
|
| * emulate it using the KAME implementation. */ |
* emulate it using the KAME implementation. */ |
| |
|
| #include "rsync.h" |
#include "rsync.h" |
| |
#include "itypes.h" |
| #include "ifuncs.h" |
#include "ifuncs.h" |
| #ifdef HAVE_NETINET_IN_SYSTM_H |
#ifdef HAVE_NETINET_IN_SYSTM_H |
| #include <netinet/in_systm.h> |
#include <netinet/in_systm.h> |
|
Line 38 extern char *bind_address;
|
Line 39 extern char *bind_address;
|
| extern char *sockopts; |
extern char *sockopts; |
| extern int default_af_hint; |
extern int default_af_hint; |
| extern int connect_timeout; |
extern int connect_timeout; |
| |
extern int pid_file_fd; |
| |
extern int diffserv; |
| |
extern char *congestion_alg; |
| |
|
| #ifdef HAVE_SIGACTION |
#ifdef HAVE_SIGACTION |
| static struct sigaction sigact; |
static struct sigaction sigact; |
|
Line 48 static int sock_exec(const char *prog);
|
Line 52 static int sock_exec(const char *prog);
|
| /* Establish a proxy connection on an open socket to a web proxy by using the |
/* Establish a proxy connection on an open socket to a web proxy by using the |
| * CONNECT method. If proxy_user and proxy_pass are not NULL, they are used to |
* CONNECT method. If proxy_user and proxy_pass are not NULL, they are used to |
| * authenticate to the proxy using the "Basic" proxy-authorization protocol. */ |
* authenticate to the proxy using the "Basic" proxy-authorization protocol. */ |
| static int establish_proxy_connection(int fd, char *host, int port, | static int establish_proxy_connection(int fd, char *host, int port, char *proxy_user, char *proxy_pass) |
| char *proxy_user, char *proxy_pass) | |
| { |
{ |
| char *cp, buffer[1024]; |
char *cp, buffer[1024]; |
| char *authhdr, authbuf[1024]; |
char *authhdr, authbuf[1024]; |
|
Line 73 static int establish_proxy_connection(int fd, char *ho
|
Line 76 static int establish_proxy_connection(int fd, char *ho
|
| authhdr = ""; |
authhdr = ""; |
| } |
} |
| |
|
| snprintf(buffer, sizeof buffer, "CONNECT %s:%d HTTP/1.0%s%s\r\n\r\n", | len = snprintf(buffer, sizeof buffer, "CONNECT %s:%d HTTP/1.0%s%s\r\n\r\n", host, port, authhdr, authbuf); |
| host, port, authhdr, authbuf); | assert(len > 0 && len < (int)sizeof buffer); |
| len = strlen(buffer); | |
| if (write(fd, buffer, len) != len) { |
if (write(fd, buffer, len) != len) { |
| rsyserr(FERROR, errno, "failed to write to proxy"); |
rsyserr(FERROR, errno, "failed to write to proxy"); |
| return -1; |
return -1; |
|
Line 161 int try_bind_local(int s, int ai_family, int ai_sockty
|
Line 163 int try_bind_local(int s, int ai_family, int ai_sockty
|
| } |
} |
| |
|
| /* connect() timeout handler based on alarm() */ |
/* connect() timeout handler based on alarm() */ |
| static RETSIGTYPE contimeout_handler(UNUSED(int val)) | static void contimeout_handler(UNUSED(int val)) |
| { |
{ |
| connect_timeout = -1; |
connect_timeout = -1; |
| } |
} |
| |
|
| |
/* Set special socket options |
| |
* |
| |
* Diffserv is a value in the range of 0-63, and needs to be shifted left |
| |
* 2 places AND treated differently for ipv4 and ipv6. |
| |
* Setting TCP congestion control is rather Linux specific (at the moment) |
| |
* and sends a varying length string to setsockopt rather than an integer |
| |
* or character. |
| |
*/ |
| |
|
| |
void set_special_sockopts(int s) |
| |
{ |
| |
#if defined(TCP_CONGESTION) |
| |
if (congestion_alg) { |
| |
if (setsockopt(s, SOL_TCP, TCP_CONGESTION, congestion_alg, strlen(congestion_alg)) == -1) |
| |
rprintf(FINFO, "Couldn't set %s congestion algorithm\n", congestion_alg); |
| |
} |
| |
#endif |
| |
|
| |
/* setting the diffserv/tos bits is different on ipv6 and |
| |
* ipv4, so we just hammer down on both and ignore the result |
| |
* And ipv6 demands an int for v. I didn't write the spec. |
| |
*/ |
| |
if (diffserv) { |
| |
int v = (diffserv & 63) <<2; |
| |
setsockopt(s,IPPROTO_IP, IP_TOS, &v, sizeof(v)); |
| |
#if defined(IPV6_TCLASS) |
| |
setsockopt(s,IPPROTO_IPV6, IPV6_TCLASS, &v, sizeof(v)); |
| |
#endif |
| |
} |
| |
} |
| |
|
| /* Open a socket to a tcp remote host with the specified port. |
/* Open a socket to a tcp remote host with the specified port. |
| * |
* |
| * Based on code from Warren. Proxy support by Stephen Rothwell. |
* Based on code from Warren. Proxy support by Stephen Rothwell. |
|
Line 182 static RETSIGTYPE contimeout_handler(UNUSED(int val))
|
Line 215 static RETSIGTYPE contimeout_handler(UNUSED(int val))
|
| * bind_addr: local address to use. Normally NULL to bind the wildcard address. |
* bind_addr: local address to use. Normally NULL to bind the wildcard address. |
| * |
* |
| * af_hint: address family, e.g. AF_INET or AF_INET6. */ |
* af_hint: address family, e.g. AF_INET or AF_INET6. */ |
| int open_socket_out(char *host, int port, const char *bind_addr, | int open_socket_out(char *host, int port, const char *bind_addr, int af_hint) |
| int af_hint) | |
| { |
{ |
| int type = SOCK_STREAM; |
int type = SOCK_STREAM; |
| int error, s, j, addr_cnt, *errnos; |
int error, s, j, addr_cnt, *errnos; |
|
Line 195 int open_socket_out(char *host, int port, const char *
|
Line 227 int open_socket_out(char *host, int port, const char *
|
| char *proxy_user = NULL, *proxy_pass = NULL; |
char *proxy_user = NULL, *proxy_pass = NULL; |
| |
|
| /* if we have a RSYNC_PROXY env variable then redirect our |
/* if we have a RSYNC_PROXY env variable then redirect our |
| * connetcion via a web proxy at the given address. */ | * connection via a web proxy at the given address. */ |
| h = getenv("RSYNC_PROXY"); |
h = getenv("RSYNC_PROXY"); |
| proxied = h != NULL && *h != '\0'; |
proxied = h != NULL && *h != '\0'; |
| |
|
|
Line 229 int open_socket_out(char *host, int port, const char *
|
Line 261 int open_socket_out(char *host, int port, const char *
|
| } |
} |
| *cp++ = '\0'; |
*cp++ = '\0'; |
| strlcpy(portbuf, cp, sizeof portbuf); |
strlcpy(portbuf, cp, sizeof portbuf); |
| if (verbose >= 2) { | if (DEBUG_GTE(CONNECT, 1)) { |
| rprintf(FINFO, "connection via http proxy %s port %s\n", |
rprintf(FINFO, "connection via http proxy %s port %s\n", |
| h, portbuf); |
h, portbuf); |
| } |
} |
|
Line 250 int open_socket_out(char *host, int port, const char *
|
Line 282 int open_socket_out(char *host, int port, const char *
|
| |
|
| for (res = res0, addr_cnt = 0; res; res = res->ai_next, addr_cnt++) {} |
for (res = res0, addr_cnt = 0; res; res = res->ai_next, addr_cnt++) {} |
| errnos = new_array0(int, addr_cnt); |
errnos = new_array0(int, addr_cnt); |
| if (!errnos) |
|
| out_of_memory("open_socket_out"); |
|
| |
|
| s = -1; |
s = -1; |
| /* Try to connect to all addresses for this machine until we get |
/* Try to connect to all addresses for this machine until we get |
|
Line 275 int open_socket_out(char *host, int port, const char *
|
Line 305 int open_socket_out(char *host, int port, const char *
|
| alarm(connect_timeout); |
alarm(connect_timeout); |
| } |
} |
| |
|
| |
set_special_sockopts(s); |
| set_socket_options(s, sockopts); |
set_socket_options(s, sockopts); |
| while (connect(s, res->ai_addr, res->ai_addrlen) < 0) { |
while (connect(s, res->ai_addr, res->ai_addrlen) < 0) { |
| if (connect_timeout < 0) |
if (connect_timeout < 0) |
|
Line 294 int open_socket_out(char *host, int port, const char *
|
Line 325 int open_socket_out(char *host, int port, const char *
|
| continue; |
continue; |
| } |
} |
| |
|
| if (proxied | if (proxied && establish_proxy_connection(s, host, port, proxy_user, proxy_pass) != 0) { |
| && establish_proxy_connection(s, host, port, | |
| proxy_user, proxy_pass) != 0) { | |
| close(s); |
close(s); |
| s = -1; |
s = -1; |
| continue; |
continue; |
| } |
} |
| if (verbose >= 3) { | if (DEBUG_GTE(CONNECT, 2)) { |
| char buf[2048]; |
char buf[2048]; |
| if ((error = getnameinfo(res->ai_addr, res->ai_addrlen, buf, sizeof buf, NULL, 0, NI_NUMERICHOST)) != 0) |
if ((error = getnameinfo(res->ai_addr, res->ai_addrlen, buf, sizeof buf, NULL, 0, NI_NUMERICHOST)) != 0) |
| snprintf(buf, sizeof buf, "*getnameinfo failure: %s*", gai_strerror(error)); |
snprintf(buf, sizeof buf, "*getnameinfo failure: %s*", gai_strerror(error)); |
|
Line 310 int open_socket_out(char *host, int port, const char *
|
Line 339 int open_socket_out(char *host, int port, const char *
|
| break; |
break; |
| } |
} |
| |
|
| if (s < 0 || verbose >= 3) { | if (s < 0 || DEBUG_GTE(CONNECT, 2)) { |
| char buf[2048]; |
char buf[2048]; |
| for (res = res0, j = 0; res; res = res->ai_next, j++) { |
for (res = res0, j = 0; res; res = res->ai_next, j++) { |
| if (errnos[j] == 0) |
if (errnos[j] == 0) |
|
Line 340 int open_socket_out(char *host, int port, const char *
|
Line 369 int open_socket_out(char *host, int port, const char *
|
| * This is based on the Samba LIBSMB_PROG feature. |
* This is based on the Samba LIBSMB_PROG feature. |
| * |
* |
| * bind_addr: local address to use. Normally NULL to get the stack default. */ |
* bind_addr: local address to use. Normally NULL to get the stack default. */ |
| int open_socket_out_wrapped(char *host, int port, const char *bind_addr, | int open_socket_out_wrapped(char *host, int port, const char *bind_addr, int af_hint) |
| int af_hint) | |
| { |
{ |
| char *prog = getenv("RSYNC_CONNECT_PROG"); |
char *prog = getenv("RSYNC_CONNECT_PROG"); |
| |
|
|
Line 359 int open_socket_out_wrapped(char *host, int port, cons
|
Line 387 int open_socket_out_wrapped(char *host, int port, cons
|
| len += hlen; |
len += hlen; |
| } |
} |
| f = prog; |
f = prog; |
| if (!(prog = new_array(char, len))) | prog = new_array(char, len); |
| out_of_memory("open_socket_out_wrapped"); | |
| for (t = prog; *f; f++) { |
for (t = prog; *f; f++) { |
| if (*f == '%') { |
if (*f == '%') { |
| switch (*++f) { |
switch (*++f) { |
|
Line 381 int open_socket_out_wrapped(char *host, int port, cons
|
Line 408 int open_socket_out_wrapped(char *host, int port, cons
|
| *t = '\0'; |
*t = '\0'; |
| } |
} |
| |
|
| if (verbose >= 2) { | if (DEBUG_GTE(CONNECT, 1)) { |
| rprintf(FINFO, "%sopening tcp connection to %s port %d\n", |
rprintf(FINFO, "%sopening tcp connection to %s port %d\n", |
| prog ? "Using RSYNC_CONNECT_PROG instead of " : "", |
prog ? "Using RSYNC_CONNECT_PROG instead of " : "", |
| host, port); |
host, port); |
|
Line 428 static int *open_socket_in(int type, int port, const c
|
Line 455 static int *open_socket_in(int type, int port, const c
|
| |
|
| socks = new_array(int, maxs + 1); |
socks = new_array(int, maxs + 1); |
| errmsgs = new_array(char *, maxs); |
errmsgs = new_array(char *, maxs); |
| if (!socks || !errmsgs) |
|
| out_of_memory("open_socket_in"); |
|
| |
|
| /* We may not be able to create the socket, if for example the |
/* We may not be able to create the socket, if for example the |
| * machine knows about IPv6 in the C library, but not in the |
* machine knows about IPv6 in the C library, but not in the |
|
Line 449 static int *open_socket_in(int type, int port, const c
|
Line 474 static int *open_socket_in(int type, int port, const c
|
| continue; |
continue; |
| } |
} |
| |
|
| |
set_special_sockopts(s); |
| setsockopt(s, SOL_SOCKET, SO_REUSEADDR, |
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, |
| (char *)&one, sizeof one); |
(char *)&one, sizeof one); |
| if (sockopts) |
if (sockopts) |
|
Line 458 static int *open_socket_in(int type, int port, const c
|
Line 484 static int *open_socket_in(int type, int port, const c
|
| |
|
| #ifdef IPV6_V6ONLY |
#ifdef IPV6_V6ONLY |
| if (resp->ai_family == AF_INET6) { |
if (resp->ai_family == AF_INET6) { |
| if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, | if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof one) < 0 |
| (char *)&one, sizeof one) < 0 | && default_af_hint != AF_INET6) { |
| && default_af_hint != AF_INET6) { | |
| close(s); |
close(s); |
| continue; |
continue; |
| } |
} |
|
Line 489 static int *open_socket_in(int type, int port, const c
|
Line 514 static int *open_socket_in(int type, int port, const c
|
| /* Only output the socket()/bind() messages if we were totally |
/* Only output the socket()/bind() messages if we were totally |
| * unsuccessful, or if the daemon is being run with -vv. */ |
* unsuccessful, or if the daemon is being run with -vv. */ |
| for (s = 0; s < ecnt; s++) { |
for (s = 0; s < ecnt; s++) { |
| if (!i || verbose > 1) | if (!i || DEBUG_GTE(BIND, 1)) |
| rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]), 0); |
rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]), 0); |
| free(errmsgs[s]); |
free(errmsgs[s]); |
| } |
} |
|
Line 529 int is_a_socket(int fd)
|
Line 554 int is_a_socket(int fd)
|
| } |
} |
| |
|
| |
|
| static RETSIGTYPE sigchld_handler(UNUSED(int val)) | static void sigchld_handler(UNUSED(int val)) |
| { |
{ |
| #ifdef WNOHANG |
#ifdef WNOHANG |
| while (waitpid(-1, NULL, WNOHANG) > 0) {} | int status; |
| | while (waitpid(-1, &status, WNOHANG) > 0) { |
| | if (WIFSIGNALED(status)) { |
| | rprintf(FLOG, |
| | "rsync error: (3) Child proccess has unexpectedly died with signal %d\n", |
| | WTERMSIG(status)); |
| | } else if (WIFEXITED(status) && WEXITSTATUS(status) == RERR_WECRASHED) { |
| | rprintf(FLOG, |
| | "rsync error: (3) Child proccess has CRASHED.\n"); |
| | } |
| | } |
| #endif |
#endif |
| #ifndef HAVE_SIGACTION |
#ifndef HAVE_SIGACTION |
| signal(SIGCHLD, sigchld_handler); |
signal(SIGCHLD, sigchld_handler); |
|
Line 544 void start_accept_loop(int port, int (*fn)(int, int))
|
Line 579 void start_accept_loop(int port, int (*fn)(int, int))
|
| { |
{ |
| fd_set deffds; |
fd_set deffds; |
| int *sp, maxfd, i; |
int *sp, maxfd, i; |
| |
#ifdef HAVE_LIBSLP |
| |
time_t next_slp_refresh; |
| |
short slp_timeout = lp_use_slp() ? lp_slp_refresh() : 0; |
| |
if (slp_timeout) { |
| |
if (slp_timeout < SLP_MIN_TIMEOUT) |
| |
slp_timeout = SLP_MIN_TIMEOUT; |
| |
/* re-register before slp times out */ |
| |
slp_timeout -= 15; |
| |
} |
| |
#endif |
| |
|
| #ifdef HAVE_SIGACTION |
#ifdef HAVE_SIGACTION |
| sigact.sa_flags = SA_NOCLDSTOP; |
sigact.sa_flags = SA_NOCLDSTOP; |
|
Line 557 void start_accept_loop(int port, int (*fn)(int, int))
|
Line 602 void start_accept_loop(int port, int (*fn)(int, int))
|
| /* ready to listen */ |
/* ready to listen */ |
| FD_ZERO(&deffds); |
FD_ZERO(&deffds); |
| for (i = 0, maxfd = -1; sp[i] >= 0; i++) { |
for (i = 0, maxfd = -1; sp[i] >= 0; i++) { |
| if (listen(sp[i], 5) < 0) { | if (listen(sp[i], lp_listen_backlog()) < 0) { |
| rsyserr(FERROR, errno, "listen() on socket failed"); |
rsyserr(FERROR, errno, "listen() on socket failed"); |
| #ifdef INET6 |
#ifdef INET6 |
| if (errno == EADDRINUSE && i > 0) { |
if (errno == EADDRINUSE && i > 0) { |
| rprintf(FINFO, | rprintf(FINFO, "Try using --ipv4 or --ipv6 to avoid this listen() error.\n"); |
| "Try using --ipv4 or --ipv6 to avoid this listen() error.\n"); | |
| } |
} |
| #endif |
#endif |
| exit_cleanup(RERR_SOCKETIO); |
exit_cleanup(RERR_SOCKETIO); |
|
Line 572 void start_accept_loop(int port, int (*fn)(int, int))
|
Line 616 void start_accept_loop(int port, int (*fn)(int, int))
|
| maxfd = sp[i]; |
maxfd = sp[i]; |
| } |
} |
| |
|
| |
#ifdef HAVE_LIBSLP |
| |
next_slp_refresh = time(NULL) + slp_timeout; |
| |
#endif |
| |
|
| /* now accept incoming connections - forking a new process |
/* now accept incoming connections - forking a new process |
| * for each incoming connection */ |
* for each incoming connection */ |
| while (1) { |
while (1) { |
| fd_set fds; |
fd_set fds; |
| pid_t pid; |
pid_t pid; |
| int fd; |
int fd; |
| |
int sel_ret; |
| struct sockaddr_storage addr; |
struct sockaddr_storage addr; |
| socklen_t addrlen = sizeof addr; |
socklen_t addrlen = sizeof addr; |
| |
#ifdef HAVE_LIBSLP |
| |
struct timeval slp_tv; |
| |
|
| |
slp_tv.tv_sec = 10; |
| |
slp_tv.tv_usec = 0; |
| |
#endif |
| |
|
| /* close log file before the potentially very long select so |
/* close log file before the potentially very long select so |
| * file can be trimmed by another process instead of growing |
* file can be trimmed by another process instead of growing |
| * forever */ |
* forever */ |
|
Line 592 void start_accept_loop(int port, int (*fn)(int, int))
|
Line 647 void start_accept_loop(int port, int (*fn)(int, int))
|
| fds = deffds; |
fds = deffds; |
| #endif |
#endif |
| |
|
| if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 1) | #ifdef HAVE_LIBSLP |
| | sel_ret = select(maxfd + 1, &fds, NULL, NULL, |
| | slp_timeout ? &slp_tv : NULL); |
| | if (sel_ret == 0 && slp_timeout && time(NULL) > next_slp_refresh) { |
| | rprintf(FINFO, "Service registration expired, refreshing it\n"); |
| | register_services(); |
| | next_slp_refresh = time(NULL) + slp_timeout; |
| | } |
| | #else |
| | sel_ret = select(maxfd + 1, &fds, NULL, NULL, NULL); |
| | #endif |
| | if (sel_ret < 1) |
| continue; |
continue; |
| |
|
| for (i = 0, fd = -1; sp[i] >= 0; i++) { |
for (i = 0, fd = -1; sp[i] >= 0; i++) { |
| if (FD_ISSET(sp[i], &fds)) { |
if (FD_ISSET(sp[i], &fds)) { |
| fd = accept(sp[i], (struct sockaddr *)&addr, | fd = accept(sp[i], (struct sockaddr *)&addr, &addrlen); |
| &addrlen); | |
| break; |
break; |
| } |
} |
| } |
} |
|
Line 610 void start_accept_loop(int port, int (*fn)(int, int))
|
Line 675 void start_accept_loop(int port, int (*fn)(int, int))
|
| |
|
| if ((pid = fork()) == 0) { |
if ((pid = fork()) == 0) { |
| int ret; |
int ret; |
| |
if (pid_file_fd >= 0) |
| |
close(pid_file_fd); |
| for (i = 0; sp[i] >= 0; i++) |
for (i = 0; sp[i] >= 0; i++) |
| close(sp[i]); |
close(sp[i]); |
| /* Re-open log file in child before possibly giving |
/* Re-open log file in child before possibly giving |
|
Line 690 void set_socket_options(int fd, char *options)
|
Line 757 void set_socket_options(int fd, char *options)
|
| |
|
| options = strdup(options); |
options = strdup(options); |
| |
|
| if (!options) |
|
| out_of_memory("set_socket_options"); |
|
| |
|
| for (tok = strtok(options, " \t,"); tok; tok = strtok(NULL," \t,")) { |
for (tok = strtok(options, " \t,"); tok; tok = strtok(NULL," \t,")) { |
| int ret=0,i; |
int ret=0,i; |
| int value = 1; |
int value = 1; |
|
Line 797 static int socketpair_tcp(int fd[2])
|
Line 861 static int socketpair_tcp(int fd[2])
|
| set_blocking(fd[1]); |
set_blocking(fd[1]); |
| |
|
| if (connect_done == 0) { |
if (connect_done == 0) { |
| if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) != 0 | if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) != 0 && errno != EISCONN) |
| && errno != EISCONN) | |
| goto failed; |
goto failed; |
| } |
} |
| |
|
|
Line 820 static int socketpair_tcp(int fd[2])
|
Line 883 static int socketpair_tcp(int fd[2])
|
| * stdout. This is used to fake a connection to a daemon for testing -- not |
* stdout. This is used to fake a connection to a daemon for testing -- not |
| * for the normal case of running SSH. |
* for the normal case of running SSH. |
| * |
* |
| * Retruns a socket which is attached to a subprocess running "prog". stdin and | * Returns a socket which is attached to a subprocess running "prog". stdin and |
| * stdout are attached. stderr is left attached to the original stderr. */ |
* stdout are attached. stderr is left attached to the original stderr. */ |
| static int sock_exec(const char *prog) |
static int sock_exec(const char *prog) |
| { |
{ |
|
Line 831 static int sock_exec(const char *prog)
|
Line 894 static int sock_exec(const char *prog)
|
| rsyserr(FERROR, errno, "socketpair_tcp failed"); |
rsyserr(FERROR, errno, "socketpair_tcp failed"); |
| return -1; |
return -1; |
| } |
} |
| if (verbose >= 2) | if (DEBUG_GTE(CMD, 1)) |
| rprintf(FINFO, "Running socket program: \"%s\"\n", prog); |
rprintf(FINFO, "Running socket program: \"%s\"\n", prog); |
| |
|
| pid = fork(); |
pid = fork(); |
|
Line 847 static int sock_exec(const char *prog)
|
Line 910 static int sock_exec(const char *prog)
|
| fprintf(stderr, "Failed to run \"%s\"\n", prog); |
fprintf(stderr, "Failed to run \"%s\"\n", prog); |
| exit(1); |
exit(1); |
| } |
} |
| exit(system(prog)); | exit(shell_exec(prog)); |
| } |
} |
| |
|
| close(fd[1]); |
close(fd[1]); |