+static int add_a_group(int f_out, const char *gname)
+{
+ gid_t gid;
+ if (!group_to_gid(gname, &gid, True)) {
+ rprintf(FLOG, "Invalid gid %s\n", gname);
+ io_printf(f_out, "@ERROR: invalid gid %s\n", gname);
+ return -1;
+ }
+ if (gid_count == MAX_GID_LIST) {
+ rprintf(FLOG, "Too many groups specified via gid parameter.\n");
+ io_printf(f_out, "@ERROR: too many groups\n");
+ return -1;
+ }
+ gid_list[gid_count++] = gid;
+ return 0;
+}
+
+static struct passwd *want_all_groups(int f_out, uid_t uid)
+{
+#if defined HAVE_GETGROUPLIST || defined HAVE_INITGROUPS
+ struct passwd *pw;
+ if ((pw = getpwuid(uid)) == NULL) {
+ rsyserr(FLOG, errno, "getpwuid failed");
+ io_printf(f_out, "@ERROR: getpwuid failed\n");
+ return NULL;
+ }
+# ifdef HAVE_GETGROUPLIST
+ /* Get all the process's groups, with the pw_gid group first. */
+ gid_count = MAX_GID_LIST;
+ if (getgrouplist(pw->pw_name, pw->pw_gid, gid_list, &gid_count) < 0) {
+ rsyserr(FLOG, errno, "getgrouplist failed");
+ io_printf(f_out, "@ERROR: getgrouplist failed\n");
+ return NULL;
+ }
+ /* Paranoia: is the default group not first in the list? */
+ if (gid_list[0] != pw->pw_gid) {
+ int j;
+ for (j = 0; j < gid_count; j++) {
+ if (gid_list[j] == pw->pw_gid) {
+ gid_list[j] = gid_list[0];
+ gid_list[0] = pw->pw_gid;
+ break;
+ }
+ }
+ }
+# else
+ /* Start with the default group and initgroups() will add the reset. */
+ gid_count = 1;
+ gid_list[0] = pw->pw_gid;
+# endif
+ return pw;
+#else
+ rprintf(FLOG, "This rsync does not support a gid of \"*\"\n");
+ io_printf(f_out, "@ERROR: invalid gid setting.\n");
+ return NULL;
+#endif
+}
+
+static int rsync_module(int f_in, int f_out, int i, const char *addr, const char *host)