rem: } else { module_dirlen = strlen(lp_path(i));
add: } else
context: static int rsync_module(int f_in, int f_out, int i){	int argc = 0;	int maxargs;	char **argv;	char **argp;	char line[MAXPATHLEN];	uid_t uid = (uid_t)-2;  /* canonically "nobody" */	gid_t gid = (gid_t)-2;	char *p;	char *addr = client_addr(f_in);	char *host = client_name(f_in);	char *name = lp_name(i);	int use_chroot = lp_use_chroot(i);	int start_glob = 0;	int ret;	char *request = NULL;	if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {		rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",			name, host, addr);		if (!lp_list(i))			io_printf(f_out, "@ERROR: Unknown module '%s'\n", name);		else {			io_printf(f_out,				  "@ERROR: access denied to %s from %s (%s)\n",				  name, host, addr);		}		return -1;	}	if (am_daemon && am_server) {		rprintf(FLOG, "rsync allowed access on module %s from %s (%s)\n",			name, host, addr);	}	if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) {		if (errno) {			rsyserr(FLOG, errno, "failed to open lock file %s",				safe_fname(lp_lock_file(i)));			io_printf(f_out, "@ERROR: failed to open lock file\n");		} else {			rprintf(FLOG, "max connections (%d) reached\n",				lp_max_connections(i));			io_printf(f_out, "@ERROR: max connections (%d) reached -- try again later\n",				lp_max_connections(i));		}		return -1;	}	auth_user = auth_server(f_in, f_out, i, addr, "@RSYNCD: AUTHREQD ");	if (!auth_user) {		rprintf(FLOG, "auth failed on module %s from %s (%s)\n",			name, host, addr);		io_printf(f_out, "@ERROR: auth failed on module %s\n", name);		return -1;	}	module_id = i;	if (lp_read_only(i))		read_only = 1;	if (lp_transfer_logging(i)) {		if (log_format_has(lp_log_format(i), 'i'))			daemon_log_format_has_i = 1;		if (daemon_log_format_has_i		    || log_format_has(lp_log_format(i), 'o'))			daemon_log_format_has_o_or_i = 1;	}	am_root = (MY_UID() == 0);	if (am_root) {		p = lp_uid(i);		if (!name_to_uid(p, &uid)) {			if (!isdigit(*(unsigned char *)p)) {				rprintf(FLOG, "Invalid uid %s\n", p);				io_printf(f_out, "@ERROR: invalid uid %s\n", p);				return -1;			}			uid = atoi(p);		}		p = lp_gid(i);		if (!name_to_gid(p, &gid)) {			if (!isdigit(*(unsigned char *)p)) {				rprintf(FLOG, "Invalid gid %s\n", p);				io_printf(f_out, "@ERROR: invalid gid %s\n", p);				return -1;			}			gid = atoi(p);		}	}	/* TODO: If we're not root, but the configuration requests	 * that we change to some uid other than the current one, then	 * log a warning. */	/* TODO: Perhaps take a list of gids, and make them into the	 * supplementary groups. */	if (use_chroot) {		module_dirlen = 0;		set_filter_dir("/", 1);	} else {		module_dirlen = strlen(lp_path(i));		set_filter_dir(lp_path(i), module_dirlen);	}	p = lp_filter(i);	parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,		   XFLG_ANCHORED2ABS);	p = lp_include_from(i);	parse_filter_file(&server_filter_list, p, MATCHFLG_INCLUDE,	    XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);	p = lp_include(i);	parse_rule(&server_filter_list, p,		   MATCHFLG_INCLUDE | MATCHFLG_WORD_SPLIT,		   XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES);	p = lp_exclude_from(i);	parse_filter_file(&server_filter_list, p, 0,	    XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);	p = lp_exclude(i);	parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,		   XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES);	log_init();	if (use_chroot) {		/*		 * XXX: The 'use chroot' flag is a fairly reliable		 * source of confusion, because it fails under two		 * important circumstances: running as non-root,		 * running on Win32 (or possibly others).  On the		 * other hand, if you are running as root, then it		 * might be better to always use chroot.		 *		 * So, perhaps if we can't chroot we should just issue		 * a warning, unless a "require chroot" flag is set,		 * in which case we fail.		 */		if (chroot(lp_path(i))) {			rsyserr(FLOG, errno, "chroot %s failed",				safe_fname(lp_path(i)));			io_printf(f_out, "@ERROR: chroot failed\n");			return -1;		}		if (!push_dir("/")) {			rsyserr(FLOG, errno, "chdir %s failed\n",				safe_fname(lp_path(i)));			io_printf(f_out, "@ERROR: chdir failed\n");			return -1;		}	} else {		if (!push_dir(lp_path(i))) {			rsyserr(FLOG, errno, "chdir %s failed\n",				safe_fname(lp_path(i)));			io_printf(f_out, "@ERROR: chdir failed\n");			return -1;		}		sanitize_paths = 1;	}	if (am_root) {		/* XXXX: You could argue that if the daemon is started		 * by a non-root user and they explicitly specify a		 * gid, then we should try to change to that gid --		 * this could be possible if it's already in their		 * supplementary groups. */		/* TODO: Perhaps we need to document that if rsyncd is		 * started by somebody other than root it will inherit		 * all their supplementary groups. */		if (setgid(gid)) {			rsyserr(FLOG, errno, "setgid %d failed", (int)gid);			io_printf(f_out, "@ERROR: setgid failed\n");			return -1;		}#ifdef HAVE_SETGROUPS		/* Get rid of any supplementary groups this process		 * might have inheristed. */		if (setgroups(1, &gid)) {			rsyserr(FLOG, errno, "setgroups failed");			io_printf(f_out, "@ERROR: setgroups failed\n");			return -1;		}#endif		if (setuid(uid)) {			rsyserr(FLOG, errno, "setuid %d failed", (int)uid);			io_printf(f_out, "@ERROR: setuid failed\n");			return -1;		}		am_root = (MY_UID() == 0);	}	io_printf(f_out, "@RSYNCD: OK\n");	maxargs = MAX_ARGS;	if (!(argv = new_array(char *, maxargs)))		out_of_memory("rsync_module");	argv[argc++] = "rsyncd";	while (1) {		if (!read_line(f_in, line, sizeof line - 1))			return -1;		if (!*line)			break;		p = line;		if (argc == maxargs) {			maxargs += MAX_ARGS;			if (!(argv = realloc_array(argv, char *, maxargs)))				out_of_memory("rsync_module");		}		if (!(argv[argc] = strdup(p)))			out_of_memory("rsync_module");		if (start_glob) {			if (start_glob == 1) {				request = strdup(p);				start_glob++;			}			glob_expand(name, &argv, &argc, &maxargs);		} else			argc++;		if (strcmp(line, ".") == 0)			start_glob = 1;	}	verbose = 0; /* future verbosity is controlled by client options */	argp = argv;	ret = parse_arguments(&argc, (const char ***) &argp, 0);	if (filesfrom_fd == 0)		filesfrom_fd = f_in;	if (request) {		if (*auth_user) {			rprintf(FLOG, "rsync %s %s from %s@%s (%s)\n",				am_sender ? "on" : "to",				request, auth_user, host, addr);		} else {			rprintf(FLOG, "rsync %s %s from %s (%s)\n",				am_sender ? "on" : "to",				request, host, addr);		}		free(request);	}#ifndef DEBUG	/* don't allow the logs to be flooded too fast */	if (verbose > lp_max_verbosity())		verbose = lp_max_verbosity();#endif	if (protocol_version < 23	    && (protocol_version == 22 || am_sender))		io_start_multiplex_out();	else if (!ret) {		/* We have to get I/O multiplexing started so that we can		 * get the error back to the client.  This means getting		 * the protocol setup finished first in later versions. */		setup_protocol(f_out, f_in);		if (!am_sender) {			/* Since we failed in our option parsing, we may not			 * have finished parsing that the client sent us a			 * --files-from option, so look for it manually.			 * Without this, the socket would be in the wrong			 * state for the upcoming error message. */			if (!files_from) {				int i;				for (i = 0; i < argc; i++) {					if (strncmp(argv[i], "--files-from", 12) == 0) {						files_from = "";						break;					}				}			}			if (files_from)				write_byte(f_out, 0);		}		io_start_multiplex_out();	}	if (!ret) {		option_error();		msleep(400);		exit_cleanup(RERR_UNSUPPORTED);	}	if (lp_timeout(i)) {		io_timeout = lp_timeout(i);		if (io_timeout < select_timeout)			select_timeout = io_timeout;	}	start_server(f_in, f_out, argc, argp);	return 0;}