problems with initialization.
Change the algorithm from trying to open an inbound socket with
getaddrinfo: keep trying suggested addresses until we find one on
which we can both get a socket and bind. Not convinced this is the
best, but it's probably better.
extern char *shell_cmd;
extern int kludge_around_eof;
extern char *bind_address;
+ extern int default_af_hint;
if (argc == 0 && !am_sender) {
extern int list_only;
if (!user) user = getenv("LOGNAME");
fd = open_socket_out_wrapped (host, rsync_port, bind_address,
- global_opts.af_hint);
+ default_af_hint);
if (fd == -1) {
exit_cleanup(RERR_SOCKETIO);
}
extern char *config_file;
extern int orig_umask;
char *pid_file;
+ extern int no_detach;
if (is_a_socket(STDIN_FILENO)) {
int i;
return start_daemon(STDIN_FILENO);
}
- if (!global_opts.no_detach)
+ if (!no_detach)
become_daemon();
if (!lp_load(config_file, 1)) {
#endif
int blocking_io=0;
-/** Global options set from command line. **/
-struct global_opts global_opts = {
+/** Network address family. **/
#ifdef INET6
- 0, /* af_hint -- allow any protocol */
+int default_af_hint = 0; /* Any protocol */
#else
- AF_INET, /* af_hint -- prefer IPv4 */
+int default_af_hint = AF_INET; /* Must use IPv4 */
#endif
- 0, /* no_detach */
-};
-int read_batch=0; /* dw */
-int write_batch=0; /* dw */
+/** Do not go into the background when run as --daemon. Good
+ * for debugging and required for running as a service on W32,
+ * or under Unix process-monitors. **/
+int no_detach = 0;
+
+
+int read_batch=0;
+int write_batch=0;
char *backup_suffix = BACKUP_SUFFIX;
char *tmpdir = NULL;
rprintf(F," --backup-dir make backups into this directory\n");
rprintf(F," --suffix=SUFFIX override backup suffix\n");
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
- rprintf(F," -l, --links preserve soft links\n");
- rprintf(F," -L, --copy-links treat soft links like regular files\n");
+ rprintf(F," -l, --links copy symlinks as symlinks\n");
+ rprintf(F," -L, --copy-links copy the referent of symlinks\n");
rprintf(F," --copy-unsafe-links copy links outside the source tree\n");
rprintf(F," --safe-links ignore links outside the destination tree\n");
rprintf(F," -H, --hard-links preserve hard links\n");
/* TODO: Should this take an optional int giving the compression level? */
{"compress", 'z', POPT_ARG_NONE, &do_compression},
{"daemon", 0, POPT_ARG_NONE, &am_daemon},
- {"no-detach", 0, POPT_ARG_NONE, &global_opts.no_detach},
+ {"no-detach", 0, POPT_ARG_NONE, &no_detach},
{"stats", 0, POPT_ARG_NONE, &do_stats},
{"progress", 0, POPT_ARG_NONE, &do_progress},
{"partial", 0, POPT_ARG_NONE, &keep_partial},
{"read-batch", 'f', POPT_ARG_STRING, &batch_ext, 'f'},
{"write-batch", 'F', POPT_ARG_NONE, &write_batch, 0},
#ifdef INET6
- {0, '4', POPT_ARG_VAL, &global_opts.af_hint, AF_INET },
- {0, '6', POPT_ARG_VAL, &global_opts.af_hint, AF_INET6 },
+ {0, '4', POPT_ARG_VAL, &default_af_hint, AF_INET },
+ {0, '6', POPT_ARG_VAL, &default_af_hint, AF_INET6 },
#endif
{0,0,0,0}
};
{
int one=1;
int s;
- struct addrinfo hints, *res, *resp;
+ struct addrinfo hints, *all_ai, *resp;
char portbuf[10];
int error;
hints.ai_socktype = type;
hints.ai_flags = AI_PASSIVE;
snprintf(portbuf, sizeof(portbuf), "%d", port);
- error = getaddrinfo(bind_address, portbuf, &hints, &res);
+ error = getaddrinfo(bind_address, portbuf, &hints, &all_ai);
if (error) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
bind_address, gai_strerror(error));
return -1;
}
- /* XXX: Do we need to care about getting multiple results
- * back? I think probably not; if the user passed
- * bind_address == NULL and we set AI_PASSIVE then we ought to
- * get a wildcard result. */
- resp = res;
- while (1) {
- s = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
-
- if (s >= 0) {
- break; /* got a socket */
- } else if ((resp = resp->ai_next)) {
- switch (errno) {
- case EPROTONOSUPPORT:
- case EAFNOSUPPORT:
- case EPFNOSUPPORT:
- case EINVAL:
- /* See if there's another address that will work... */
- continue;
- }
+ /* 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
+ * kernel. */
+ for (resp = all_ai; resp; resp = resp->ai_next) {
+ s = socket(resp->ai_family, resp->ai_socktype,
+ resp->ai_protocol);
+
+ if (s == -1)
+ /* See if there's another address that will work... */
+ continue;
+
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&one, sizeof one);
+
+ /* now we've got a socket - we need to bind it */
+ if (bind(s, all_ai->ai_addr, all_ai->ai_addrlen) < 0) {
+ /* Nope, try another */
+ close(s);
+ continue;
}
- rprintf(FERROR, RSYNC_NAME ": open inbound socket"
- "(dom=%d, type=%d, proto=%d) failed: %s\n",
- resp->ai_family, resp->ai_socktype, resp->ai_protocol,
- strerror(errno));
- goto fail;
+ return s;
}
- setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
-
- /* now we've got a socket - we need to bind it */
- if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
- rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
- close(s);
- goto fail;
- }
-
- return s;
+ rprintf(FERROR, RSYNC_NAME ": open inbound socket on port %d failed: "
+ "%s\n",
+ port,
+ strerror(errno));
-fail:
- freeaddrinfo(res);
+ freeaddrinfo(all_ai);
return -1;
}
{
int s;
extern char *bind_address;
+ extern int default_af_hint;
/* open an incoming socket */
- s = open_socket_in(SOCK_STREAM, port, bind_address,
- global_opts.af_hint);
+ s = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
if (s == -1)
exit_cleanup(RERR_SOCKETIO);